cortado-0.6.0/ChangeLog100644 0 0 213607 11270111317 12114 0ustar 0 0 2007-05-28 Wim Taymans * src/com/fluendo/jheora/DCTDecode.java: (DCTDecode.....ExpandKFBlock), (DCTDecode.....ExpandBlock): * src/com/fluendo/jheora/Info.java: (Info): * src/com/fluendo/jheora/Playback.java: (Playback), (Playback.clearTmpBuffers), (Playback.initTmpBuffers), (Playback.initHuffmanTrees), (Playback.copyQTables): * src/com/fluendo/jheora/Quant.java: (Quant.readQTables), (Quant), (Quant.BuildQuantIndex_Generic), (Quant.init_dequantizer): Add support for 6 matrices in the decoder. Fixes #611. 2006-12-11 Wim Taymans Patch by: Tahseen Mohammad * src/com/fluendo/plugin/OggDemux.java: (OggDemux.....OggStream.OggChain.pushPage): Ignore annodex streams when discovering streams. 2006-11-21 Thomas Vander Stichele * src/com/fluendo/player/Cortado.java: (Cortado...paint): Log when appletDimension is wrong. height == statusHeight should be acceptable. 2006-11-17 Michael Smith * src/com/fluendo/plugin/AudioSinkJ2.java: (AudioSinkJ2.open): Attempt to use Real Alsa Devices instead of the software mixer, which doesn't provide good sync, if possible. 2006-11-16 Michael Smith * src/com/fluendo/player/Cortado.java: (Cortado...init): Use seekable parameter instead of live to determine seekability. 2006-11-16 Wim Taymans * src/com/fluendo/player/Cortado.java: (Cortado...actionPerformed), (Cortado...realRun), (Cortado...mouseDragged), (Cortado...mouseMoved), (Cortado...handleMessage), (Cortado...newState), (Cortado...newSeek), (Cortado...start): Handle resize correctly. * src/com/fluendo/plugin/VideoSink.java: (VideoSink.setCapsFunc), (VideoSink.render), (VideoSink), (VideoSink.getFactoryName), (VideoSink.setProperty): Fix keep-aspect. Added scale property. 2006-11-16 Wim Taymans * src/com/fluendo/jst/Message.java: (Message), (Message.toString), (Message.newEOS), (Message.newError), (Message.newWarning), (Message.newStateDirty): Add duration message. * README: * src/com/fluendo/player/Cortado.java: (Cortado), (Cortado...getAppletInfo), (Cortado...getRevision), (Cortado...getParameterInfo), (Cortado...init), (Cortado...handleMessage): Make live and seekable enums so that they can be configured automatically on request. When we get a duration message, make the stream seekable and non-live in auto mode. * src/com/fluendo/plugin/HTTPSrc.java: (HTTPSrc.getInputStream): Post duration message when the length is known. 2006-11-16 Wim Taymans * src/com/fluendo/plugin/OggDemux.java: (OggDemux.....OggStream), (OggDemux.....OggStream.OggStream), (OggDemux.....OggStream.deActivate), (OggDemux.....OggStream.reStart): Get the time right for streams that don't start with timestamp 0. 2006-11-16 Wim Taymans * README: * src/com/fluendo/player/Cortado.java: (Cortado), (Cortado..getParameterInfo), (Cortado..init): * src/com/fluendo/player/Status.java: (Status), (Status.paintPercent), (Status.paintButton1), (Status.paintTime), (Status.paintSpeaker), (Status.paint), (Status.setMessage), (Status.setHaveAudio), (Status.setHavePercent), (Status.setSeekable), (Status.mousePressed), (Status.mouseReleased): Added a live property to disable PAUSE. 2006-11-16 Wim Taymans * src/com/fluendo/plugin/OggDemux.java: (OggDemux.....OggStream.reStart): Stream time starts from 0 2006-11-03 Thomas Vander Stichele * build.xml: * scripts/update-source-info: ready for automated building 2006-11-03 Thomas Vander Stichele * cortado.spec: delete * cortado.spec.in: template for cortado.spec * scripts/update-spec-file: add a script to generate cortado.spec from template, filling in Version and Release information Use Release tag to keep track of svn revision, branch and status if the nano is set * build.xml: add a spec target 2006-11-03 Thomas Vander Stichele * scripts/update-source-info: add a script to generate src/com/fluendo/jst/SourceInfo.java This file describes the repository version of the source code. * build.xml: use the new script to generate SourceInfo.java * src/com/fluendo/player/Cortado.java: (Cortado.AboutFrame.AboutFrame): Get the source info and display it This makes sure that a cortado built from a dist still has this revision information 2006-11-03 Wim Taymans * src/com/fluendo/plugin/HTTPSrc.java: (HTTPSrc.Pad), (HTTPSrc.openWithConnection), (HTTPSrc.openWithSocket): Set default contentLength to -1 and take care we don't use invalid contentLength. 2006-11-02 Wim Taymans * src/com/fluendo/player/Status.java: (Status.setBufferPercent): Use correct variable... 2006-11-02 Wim Taymans * src/com/fluendo/player/Status.java: (Status.paint), (Status.intersectSeekbar), (Status.mouseMoved): Don't allow the user to press play/pause when we are buffering. 2006-11-02 Wim Taymans * src/com/fluendo/player/Status.java: (Status.paint): Don't paint the time if the applet is buffering. 2006-11-02 Wim Taymans * src/com/fluendo/player/Status.java: (Status.paint): Rearange status area, always show start/stop even if the file is not seekable. 2006-11-02 Wim Taymans * src/com/fluendo/player/Cortado.java: (Cortado..stop): Ignore potential errors in shutdown. 2006-11-02 Wim Taymans * src/com/fluendo/player/Cortado.java: (Cortado..init): Some more debug. * src/com/fluendo/plugin/HTTPSrc.java: (HTTPSrc), (HTTPSrc.Pad), (HTTPSrc.openWithConnection), (HTTPSrc.getInputStream), (HTTPSrc.getFactoryName): Keep track of offset, Don't rely on the server sending EOS. close connection on EOS. Work around EOS bug in MS JVM with twisted by not reading the last byte. 2006-11-01 Wim Taymans * src/com/fluendo/plugin/AudioSink.java: (AudioSink.AudioClock), (AudioSink.AudioClock.setStarted), (AudioSink.RingBuffer.commit), (AudioSink.RingBuffer.setSample), (AudioSink.RingBuffer.pause), (AudioSink.RingBuffer.stop): Remove the lock of the clock to further avoid deadly embraces. 2006-11-01 Wim Taymans * src/com/fluendo/player/Cortado.java: (Cortado..getParam), (Cortado..getBoolParam), (Cortado.), (Cortado..getDoubleParam), (Cortado..getIntParam), (Cortado..shutDown), (Cortado..init): Print parameter values and how they are parsed. Accept 1 as true for boolean parameters. 2006-11-01 Wim Taymans * src/com/fluendo/plugin/AudioSink.java: (AudioSink.RingBuffer), (AudioSink.RingBuffer.setAutoStart): Fix potential deadly embrace. 2006-11-01 Wim Taymans * src/com/fluendo/player/CortadoPipeline.java: (CortadoPipeline.doSendEvent): Wait for preroll befre setting the state to PLAYING after a seek. 2006-11-01 Wim Taymans * src/com/fluendo/jst/Sink.java: (Sink.Pad): Backport race fix in the sink where the state change function could have updated the state variables before the streaming thread did, resulting in an inconsistent state. 2006-11-01 Wim Taymans * src/com/fluendo/jst/Sink.java: (Sink), (Sink.Pad), (Sink.query), (Sink.changeState): Make position reporting much more accurate. 2006-11-01 Wim Taymans * src/com/fluendo/jst/Element.java: (Element.postMessage): cleanup * src/com/fluendo/jst/SystemClock.java: (SystemClock.waitFunc): When we are right on time, we return OK. * src/com/fluendo/player/Cortado.java: (Cortado..realRun), (Cortado..paint), (Cortado.), (Cortado..mousePressed), (Cortado..mouseReleased), (Cortado..start), (Cortado..stop): Try to limit the number of repaints. Cancel any pending mouse operations in the status bar when we release the mouse button outside of it. * src/com/fluendo/player/Status.java: (Status.paint), (Status.setHaveAudio), (Status), (Status.setHavePercent), (Status.setSeekable), (Status.intersectSeekbar), (Status.findComponent), (Status.mouseReleased), (Status.mouseDragged): Try to limit the number of repaints. 2006-10-26 Thomas Vander Stichele * HACKING: * TODO: add some notes * build.properties: * build.xml: * cortado.spec: back to TRUNK * cortado.doap: fix === release 0.2.2 === 2006-10-26 Thomas Vander Stichele * NEWS: * RELEASE: * build.properties: * cortado.doap: Releasing 0.2.2, "Really Tested Verily Exceptionally" 2006-10-26 Thomas Vander Stichele * TODO: * build.xml: * cortado.doap: * cortado.spec: add doap file 2006-10-26 Thomas Vander Stichele * src/com/fluendo/player/CortadoPipeline.java: (CortadoPipeline.build): wrap completely in try block and use extra var 2006-10-26 Thomas Vander Stichele * src/com/fluendo/player/CortadoPipeline.java: (CortadoPipeline.build): Microsoft VM does not allow accessing http.agent, so try/catch 2006-10-26 Thomas Vander Stichele * build.xml: make sure building the player depends on distinfo target * src/com/fluendo/player/CortadoPipeline.java: (CortadoPipeline.build): add a space 2006-10-26 Thomas Vander Stichele * build.xml: separate dist-time variables in to separate class, since it should be decided at dist time and not build time * scripts/get-branch: * scripts/get-revision: make scripts work in the absence of .svn dirs, returning (unknown) * src/com/fluendo/player/Cortado.java: (Cortado.AboutFrame.AboutFrame): * src/com/fluendo/player/CortadoPipeline.java: (CortadoPipeline.build): Try to get the User-Agent to include http.agent if available 2006-10-26 Thomas Vander Stichele * build.xml: * scripts/get-branch: * scripts/get-revision: two scripts to help identify branch and revision/modification * src/com/fluendo/player/Cortado.java: (Cortado.AboutFrame.AboutFrame): * src/com/fluendo/player/CortadoPipeline.java: (CortadoPipeline), (CortadoPipeline.build): * src/com/fluendo/plugin/HTTPSrc.java: (HTTPSrc), (HTTPSrc.openWithConnection), (HTTPSrc.setProperty): set User-Agent string so that we identify ourselves with version of cortado, version of Java VM, and os name 2006-10-25 Wim Taymans * src/com/fluendo/player/Cortado.java: (Cortado..init): Disable seeking for MS JVM. 2006-10-25 Wim Taymans * src/com/fluendo/plugin/VideoSink.java: (VideoSink.setCapsFunc): Add comment. 2006-10-25 Wim Taymans * src/com/fluendo/plugin/VideoSink.java: (VideoSink.setCapsFunc): Don't mess with the component size, the parent does that for us. 2006-10-25 Wim Taymans * src/com/fluendo/jst/Pipeline.java: (Pipeline.reCalcState): release lock when continuing the state change. 2006-10-25 Wim Taymans * src/com/fluendo/jst/Pipeline.java: (Pipeline.doChildStateChange): More DEBUG. * src/com/fluendo/plugin/OggDemux.java: (OggDemux.....OggStream.Pad): Make sure the streaming thread is not running when we do our cleanup. 2006-10-25 Wim Taymans * src/com/fluendo/jst/Pipeline.java: (Pipeline.shutDown): Don't join the state thread, it might be performing a callback when being joined. 2006-10-25 Wim Taymans * src/com/fluendo/jst/Pad.java: (Pad), (Pad.pauseTask): Take lock a little differently. * src/com/fluendo/jst/Pipeline.java: (Pipeline.shutDown): Don't try to join the bus thread as this might cause a deadly embrace. * src/com/fluendo/plugin/OggDemux.java: (OggDemux.....OggStream.reStart): Add some debug for the segment/timestamps 2006-10-25 Wim Taymans * src/com/fluendo/jst/Pad.java: (Pad.startTask): Avoid deadly embrace, the variable is now unprotected but that is fine. * src/com/fluendo/jst/Sink.java: (Sink.Pad): * src/com/fluendo/plugin/HTTPSrc.java: (HTTPSrc.Pad), (HTTPSrc), (HTTPSrc.openWithConnection), (HTTPSrc.openWithSocket), (HTTPSrc.getInputStream): * src/com/fluendo/plugin/OggDemux.java: (OggDemux.....OggStream.OggChain.activate), (OggDemux.....OggStream.OggChain.deActivate), (OggDemux.....OggStream.OggChain.pushPage), (OggDemux.....OggStream.Pad): * src/com/fluendo/plugin/Queue.java: (Queue.Pad): * src/com/fluendo/plugin/TheoraDec.java: (TheoraDec..Pad): * src/com/fluendo/plugin/VorbisDec.java: (VorbisDec..Pad): Fix debug. Don't try to seek percentagesize when we don't know the total length. 2006-10-25 Wim Taymans * src/com/fluendo/jst/Pad.java: (Pad.startTask), (Pad.stopTask): Protect task state with streamLock. * src/com/fluendo/jst/Pipeline.java: (Pipeline.doChildStateChange): * src/com/fluendo/jst/Sink.java: (Sink.changeState): Add debug info for state changes. * src/com/fluendo/player/Cortado.java: (Cortado..handleMessage): Fix indentation. * src/com/fluendo/player/Status.java: (Status.mousePressed), (Status.mouseReleased), (Status.mouseMoved): Don't try to seek when we are stopped. * src/com/fluendo/plugin/AudioSink.java: (AudioSink.RingBuffer.setAutoStart): Fix potential deadly embracy between clock lock and ringbuffer lock. * src/com/fluendo/plugin/AudioSinkJ2.java: (AudioSinkJ2.delay): Add debug info. * src/com/fluendo/plugin/HTTPSrc.java: (HTTPSrc.Pad), (HTTPSrc.openWithConnection), (HTTPSrc), (HTTPSrc.openWithSocket), (HTTPSrc.getInputStream): Add more debug info. Catch seek failures in a better way. Add start of IE JVM compatible HTTP range requests. * src/com/fluendo/plugin/OggDemux.java: (OggDemux.....OggStream.Pad): Don't deactivate non-existing chains. 2006-10-24 Thomas Vander Stichele * src/com/fluendo/player/Cortado.java: (Cortado..getAppletInfo), (Cortado..init), (Cortado.AppFrame.windowDeiconified), (Cortado.AppFrame), (Cortado.AppFrame.windowIconified), (Cortado.AppFrame.windowOpened), (Cortado), (Cortado.AboutFrame.AboutFrame): trying to get svn revision in the output 2006-10-24 Wim Taymans * src/com/fluendo/player/Status.java: (Status.paint): Don't crash on null pointers. 2006-10-24 Wim Taymans * src/com/fluendo/jst/Pad.java: (Pad.run), (Pad), (Pad.startTask), (Pad.pauseTask): Catch and report Exceptions exiting the taskFunc instead of stopping the task. Fix possible race in shutting down a task. * src/com/fluendo/jst/Sink.java: (Sink.Pad): Catch prerol/render Exception and post an error. * src/com/fluendo/player/Cortado.java: (Cortado..init), (Cortado..newSeek), (Cortado.), (Cortado..start): Add some more debug info. * src/com/fluendo/player/CortadoPipeline.java: (CortadoPipeline.doSendEvent): Refuse a seek when we are not ready yet 2006-10-24 Wim Taymans * src/com/fluendo/jst/Object.java: (Object.Object): Call super constructor * src/com/fluendo/player/Cortado.java: (Cortado..getEnum), (Cortado..init), (Cortado..actionPerformed), (Cortado..getGraphics), (Cortado.), (Cortado..run), (Cortado..realRun), (Cortado..newState), (Cortado..newSeek), (Cortado..start): Remove a bunch of synchronized calls that could potentially lock up the AWT thread. Add synchronized calls to init/start/stop * src/com/fluendo/plugin/HTTPSrc.java: (HTTPSrc.getInputStream): Do some stuff differently. 2006-10-24 Wim Taymans * src/com/fluendo/jst/Bus.java: (Bus), (Bus.post), (Bus.poll): Implement flush(). * src/com/fluendo/jst/Pipeline.java: (Pipeline), (Pipeline.BusThread), (Pipeline.StateThread), (Pipeline.Pipeline): cleanup threads. * src/com/fluendo/jst/Pad.java: (Pad), (Pad.run): * src/com/fluendo/player/Cortado.java: (Cortado..start): * src/com/fluendo/plugin/HTTPSrc.java: (HTTPSrc.Pad), (HTTPSrc.getInputStream): * src/com/fluendo/plugin/Queue.java: (Queue.Pad): Give Threads a name. Don't send range for offset 0. * src/com/fluendo/utils/Debug.java: (Debug): Add code to generate unique ids. 2006-10-24 Wim Taymans * src/com/fluendo/jst/Sink.java: (Sink.Pad): Add needed locks. * src/com/fluendo/plugin/HTTPSrc.java: (HTTPSrc.getInputStream): Work around IE bug of parsing absolute URLS in a documentBase. 2006-10-24 Wim Taymans * src/com/fluendo/plugin/HTTPSrc.java: (HTTPSrc.Pad): Only push EOS on fatal errors so we don't screw up seeking. 2006-10-23 Wim Taymans * README: Adds docs about hideTimeout param. * src/com/fluendo/player/Cortado.java: (Cortado..init), (Cortado..run), (Cortado.), (Cortado..realRun), (Cortado..paint), (Cortado..setStatusVisible), (Cortado..handleMessage), (Cortado..doPause), (Cortado..doPlay), (Cortado..doStop): Add hideTimeout param. Fix stop again. 2006-10-23 Wim Taymans * README: Document javascrip methods. * src/com/fluendo/player/Cortado.java: (Cortado..handleMessage): Add doPlay(),doPause(),doStop(),doSeek() methods so that they can be used from javascript. Fixes #155 2006-10-23 Wim Taymans * src/com/fluendo/jheora/YUVBuffer.java: (YUVBuffer.prepareRGBData): Catch Exceptions while doing color conversions. Fixes #283. * src/com/fluendo/player/Cortado.java: (Cortado..handleMessage): Don't overwrite error messages. * src/com/fluendo/player/CortadoPipeline.java: (CortadoPipeline.buildMultipart), (CortadoPipeline.cleanup): Post an error when the media type cannot be found. * src/com/fluendo/plugin/HTTPSrc.java: (HTTPSrc.Pad): Post an error when streaming stops. 2006-10-23 Wim Taymans * src/com/fluendo/player/Cortado.java: (Cortado..handleMessage): Make sure we never overwrite error messages. Fixes #351. 2006-10-23 Wim Taymans * README: Add showStatus param * src/com/fluendo/player/Cortado.java: (Cortado), (Cortado..getParameterInfo), (Cortado..getParam), (Cortado..shutdown), (Cortado.), (Cortado..init), (Cortado..realRun), (Cortado..paint), (Cortado..setStatusVisible), (Cortado..intersectStatus), (Cortado..mouseClicked), (Cortado..mouseEntered), (Cortado..mouseExited), (Cortado..mousePressed), (Cortado..mouseReleased), (Cortado..mouseDragged), (Cortado..mouseMoved), (Cortado..handleMessage), (Cortado..newState): Add showStatus param. Handle hiding/showing of status area based on param. Fixes #389. * src/com/fluendo/player/Status.java: (Status.setState): Don't error out when the statusbar is invisible when we hover over it. 2006-10-23 Wim Taymans * README: Add new properties to README 2006-10-23 Wim Taymans * src/com/fluendo/player/Cortado.java: (Cortado), (Cortado.handleMessage): Handle errors a bit better. * src/com/fluendo/player/CortadoPipeline.java: (CortadoPipeline), (CortadoPipeline.padAdded), (CortadoPipeline.cleanup): Do some more cleanups. 2006-10-23 Wim Taymans * src/com/fluendo/jst/Pipeline.java: (Pipeline), (Pipeline.enumSinks), (Pipeline.reCalcState), (Pipeline.doChildStateChange), (Pipeline.changeState): Catch, store, replace EOS messages and detect when all sinks posted EOS so that we can forward EOS to the app. * src/com/fluendo/jst/Sink.java: (Sink.Pad): Remove locks, they are already taken. * src/com/fluendo/player/Cortado.java: (Cortado.handleMessage): Stop playback on EOS. * src/com/fluendo/plugin/TheoraDec.java: (TheoraDec..Pad): * src/com/fluendo/plugin/VorbisDec.java: (VorbisDec..Pad): Add some debugging in EOS. 2006-10-22 Wim Taymans * src/com/fluendo/player/Cortado.java: (Cortado.init): * src/com/fluendo/player/CortadoPipeline.java: (CortadoPipeline), (CortadoPipeline.setComponent), (CortadoPipeline.getComponent), (CortadoPipeline.build): Set documentBase when configuring HTTPSrc. * src/com/fluendo/plugin/HTTPSrc.java: (HTTPSrc), (HTTPSrc.getInputStream), (HTTPSrc.HTTPSrc), (HTTPSrc.setProperty): Add documentBase property and parse the URL in that context. Fixes #467. 2006-10-22 Wim Taymans * src/com/fluendo/jst/Pad.java: (Pad): Add helper function. * src/com/fluendo/plugin/OggDemux.java: (OggDemux.....OggStream), (OggDemux.....OggStream.OggStream), (OggDemux.....OggStream.markDiscont), (OggDemux.....OggStream.reset), (OggDemux.....OggStream.isComplete), (OggDemux.....OggStream.activate), (OggDemux.....OggStream.pushPacket), (OggDemux.....OggStream.Pad): Combine the flow of all streams so that we don't crap out when only one stream is linked. Fixes #434 2006-10-22 Wim Taymans * README: Review readme, Fixes #390. * src/com/fluendo/jst/Sink.java: (Sink.Pad): Small cleanup. * src/com/fluendo/player/Cortado.java: (Cortado.newState): Remove superfluous setState call. 2006-10-22 Wim Taymans * src/com/fluendo/jst/Element.java: (Element), (Element.getStateNext), (Element.continueState): Make state transitions more debuggable. Mark element as busy while it performs a state change. * src/com/fluendo/jst/Pipeline.java: (Pipeline), (Pipeline.Pipeline), (Pipeline.add), (Pipeline.remove), (Pipeline.SortedEnumerator.queueNextElement), (Pipeline.SinkEnumerator.nextElement), (Pipeline.SinkEnumerator), (Pipeline.enumSinks), (Pipeline.handleSyncMessage), (Pipeline.getState), (Pipeline.reCalcState): Handle switching of clock providers. Mark state dirty when removing elements. Add helper method to mark state dirty and force a state recalc. * src/com/fluendo/player/CortadoPipeline.java: (CortadoPipeline.padRemoved): Remove unused sinks after all media is detected. (Fixes #157) 2006-10-21 Wim Taymans * src/com/fluendo/jst/Pipeline.java: (Pipeline.doChildStateChange): changeState is supposed to be protected. * src/com/fluendo/player/Cortado.java: (Cortado), (Cortado.getParameterInfo), (Cortado.init), (Cortado.run), (Cortado.start): Fix statusThread not working after going to STOP Move pipeline construction to the state change. * src/com/fluendo/player/CortadoPipeline.java: (CortadoPipeline), (CortadoPipeline.setupAudioDec), (CortadoPipeline.setupVideoDec), (CortadoPipeline.padAdded), (CortadoPipeline.setUrl), (CortadoPipeline.getUrl), (CortadoPipeline.setUserId), (CortadoPipeline.setPassword), (CortadoPipeline.enableAudio), (CortadoPipeline.isAudioEnabled), (CortadoPipeline.enableVideo), (CortadoPipeline.isVideoEnabled), (CortadoPipeline.setComponent), (CortadoPipeline.getComponent), (CortadoPipeline.setBufferSize), (CortadoPipeline.getBufferSize), (CortadoPipeline.setBufferLow), (CortadoPipeline.getBufferLow), (CortadoPipeline.setBufferHigh), (CortadoPipeline.getBufferHigh), (CortadoPipeline.buildOgg), (CortadoPipeline.buildMultipart), (CortadoPipeline.capsChanged), (CortadoPipeline.noSuchElement), (CortadoPipeline.build): Fix cleanup when going to STOP. Give better error messages for missing codecs. * src/com/fluendo/plugin/OggDemux.java: (OggDemux.....OggStream.Pad): * src/com/fluendo/plugin/HTTPSrc.java: (HTTPSrc.Pad): * src/com/fluendo/plugin/Queue.java: (Queue.Pad): * src/com/fluendo/plugin/TheoraDec.java: (TheoraDec..changeState): Do some more cleanups when stopping/starting. 2006-10-19 Wim Taymans Patch by . * src/com/fluendo/jst/ElementFactory.java: Don't try to load the .ini file from the webserver. Fixes #387. * src/com/fluendo/player/Status.java: (Status.paintPlayPause), (Status.paintStop), (Status.paintSeekBar): Change the colors a bit to make the buttons more visible. 2006-10-19 Wim Taymans * src/com/fluendo/jst/Pipeline.java: (Pipeline), (Pipeline.doSeek): Improve handling of seek wrt state changes and errors. * src/com/fluendo/player/Cortado.java: (Cortado), (Cortado.getParameterInfo), (Cortado.init), (Cortado.run), (Cortado.handleMessage), (Cortado.newState), (Cortado.newSeek), (Cortado.start): Add autoPlay option. Fixes #384. Simplify state management a little. 2006-10-19 Wim Taymans * src/com/fluendo/player/Status.java: (Status), (Status.intersectButton2), (Status.intersectSeeker), (Status.findComponent), (Status.mouseClicked), (Status.mouseEntered), (Status.mouseExited), (Status.mousePressed), (Status.mouseReleased), (Status.mouseDragged), (Status.mouseMoved): Allow seeking by clicking on the timeline instead of trying to grab the slider. Fixes #358. 2006-10-19 Wim Taymans * src/com/fluendo/jheora/DCTDecode.java: (DCTDecode.....CopyRecon), (DCTDecode.....CopyNotRecon), (DCTDecode.....ReconRefFrames): Move UpdateUMVBorder after the loop functions. * src/com/fluendo/jheora/iDCT.java: (iDCT.IDctSlow), (iDCT.IDct10): Update IDCT 16 bit truncating updates. * src/com/fluendo/player/Cortado.java: (Cortado), (Cortado.getParameterInfo), (Cortado.init), (Cortado.getGraphics), (Cortado.paint): Remove framerate property Added statusHeight property to configure the size of the status area. * src/com/fluendo/player/Status.java: (Status), (Status.paintStop), (Status.paintMessage), (Status.paintBuffering), (Status.paint), (Status.setHavePercent), (Status.setSeekable), (Status.setState), (Status.intersectButton1), (Status.intersectButton2), (Status.intersectSeek), (Status.mouseReleased), (Status.mouseDragged): Make statusHeight configurable. Make the slider handle a bit bigger. === release 0.2.1 === 2006-09-14 Thomas Vander Stichele * NEWS: * RELEASE: * build.properties: releasing 0.2.1, "Flapoorke" 2006-09-14 Thomas Vander Stichele patch by: * README: fix bufferSize default values 2006-08-31 Thomas Vander Stichele * build.xml: separate out install_applet, install_class, install_doc * cortado.spec: add a first spec file 2006-08-23 Wim Taymans * src/com/fluendo/jst/Message.java: (Message.newError): Add constructor for WARNING messages. * src/com/fluendo/plugin/OggDemux.java: (OggDemux), (OggDemux.....OggStream), (OggDemux.....OggStream.bufferFromPacket), (OggDemux.....OggStream.OggChain), (OggDemux.....OggStream.OggChain.OggChain), (OggDemux.....OggStream.OggChain.isActive), (OggDemux.....OggStream.OggChain.activate), (OggDemux.....OggStream.OggChain.deActivate), (OggDemux.....OggStream.OggChain.reStart), (OggDemux.....OggStream.OggChain.findStream), (OggDemux.....OggStream.OggChain.resetStreams), (OggDemux.....OggStream.OggChain.forwardEvent), (OggDemux.....OggStream.OggChain.pushPage), (OggDemux.....OggStream.Pad), (OggDemux.....OggStream.getFactoryName), (OggDemux.....OggStream.getMime): Improve how new streams are typefound and handled. Added field to mark the stream type. Add skeleton and CMML stream detection very losely based on a patch by Tahseen Mohammad. Skip unknown and non media streams. Fix compilation. Use startsWith in typefind to reduce code. * src/com/fluendo/plugin/TheoraDec.java: (TheoraDec..getMime): * src/com/fluendo/plugin/VorbisDec.java: (VorbisDec..getMime): Use startsWith to reduce code. * src/com/fluendo/utils/MemUtils.java: (MemUtils..cmp), (MemUtils..set): Add startsWith mostly to check for signatures in typefinding. Make functions final to improve inlining. 2006-07-07 Wim Taymans * src/com/fluendo/plugin/OggDemux.java: Improve user experience (tm) 2006-07-07 Wim Taymans * src/com/fluendo/plugin/OggDemux.java: Don't try to push events when we have no chain. Post an error if we run EOS and still haven't found a chain. 2006-05-19 Thomas Vander Stichele * build.properties: back to TRUNK === release 0.2.0 === 2006-05-19 Thomas Vander Stichele * HACKING: * NEWS: * README: * RELEASE: * build.xml: make release target build everything, plus distcheck add release notes, update other notes Releasing 0.2.0, "Broken Record" 2006-05-19 Thomas Vander Stichele * build.xml: add a release target 2006-05-19 Thomas Vander Stichele * build.config.sample: * build.properties: * build.xml: change "release" type to "stripped" type 2006-05-19 Thomas Vander Stichele * build.xml: now actually fix make distcheck by disting jst code 2006-05-19 Thomas Vander Stichele * build.xml: fix distcheck; it was actually building inplace and thus not catching missing jst code 2006-05-19 Thomas Vander Stichele * README: update properties in use * src/com/fluendo/player/Cortado.java: (Cortado), (Cortado.getParameterInfo), (Cortado.shutdown), (Cortado.init), (AboutFrame.AboutFrame): * src/com/fluendo/player/Status.java: use a double for duration, is more intuitive than HMMSS only mention audio backend details if the applet is configured to play audio show VM information in about box 2006-05-19 Wim Taymans * src/com/fluendo/player/Cortado.java: (Cortado), (Cortado.getParameterInfo), (Cortado.init): Remove some unused properties 2006-05-17 Zaheer Abbas Merali * src/com/fluendo/player/Cortado.java: (Cortado.stringToTime): Bounds checking! 2006-03-20 Thomas Vander Stichele * src/com/fluendo/plugin/AudioSinkJ2.java: (AudioSinkJ2.write): * src/com/fluendo/plugin/AudioSinkSA.java: (AudioSinkSA...RingReader.RingReader): fix more warnings, one error left 2006-03-20 Thomas Vander Stichele * src/com/fluendo/plugin/AudioSink.java: (AudioSink.RingBuffer.acquire): * src/com/fluendo/plugin/OggDemux.java: (OggDemux...OggStream.pushPacket): * src/com/fluendo/plugin/TheoraDec.java: (TheoraDec.), (TheoraDec..getFirstTs): * src/com/fluendo/plugin/VorbisDec.java: (VorbisDec.), (VorbisDec..getFirstTs): Fix some warnings 2006-03-20 Thomas Vander Stichele * build.xml: apparently 1.2 is not accepted, and it needs to be 1.3 ? Hope this is ok, need to double check on 1.1 VM's. 2006-03-20 Thomas Vander Stichele * build.xml: add source="1.2" to javac targets, because some javac's and ant complain about this 2006-03-20 Wim Taymans * src/com/fluendo/plugin/HTTPSrc.java: (HTTPSrc.Pad), (HTTPSrc), (HTTPSrc.getInputStream): Do typefind on the data instead of trusting the servers contentType. Fixes #317 * src/com/fluendo/plugin/OggDemux.java: (OggDemux), (OggDemux...OggStream.getMime): Implement typeFind function. 2006-03-20 Thomas Vander Stichele * Makefile: removed * build.xml: added dist, distcheck and distclean targets 2006-03-20 Wim Taymans * src/com/fluendo/jst/Pad.java: (Pad.Pad), (Pad.eventFunc), (Pad), (Pad.sendEvent): Don't crash when printing a pad name without parent. Grab streamLock when needed. * src/com/fluendo/player/Cortado.java: (Cortado.init): Build pipeline after we have the needed infrastructure to handle errors and such. * src/com/fluendo/player/CortadoPipeline.java: (CortadoPipeline.padAdded), (CortadoPipeline.setBufferLow), (CortadoPipeline), (CortadoPipeline.getBufferLow), (CortadoPipeline.setBufferHigh), (CortadoPipeline.getBufferHigh), (CortadoPipeline.buildOgg), (CortadoPipeline.buildMultipart), (CortadoPipeline.capsChanged), (CortadoPipeline.noSuchElement), (CortadoPipeline.build): Post an error when we cannot create an element. * src/com/fluendo/plugin/OggDemux.java: (OggDemux..OggStream.deActivate), (OggDemux..OggStream.pushPacket), (OggDemux..OggStream.OggChain.isActive), (OggDemux..OggStream.OggChain), (OggDemux..OggStream.OggChain.activate), (OggDemux..OggStream.Pad): First remove pad so we can throw away the eos event. Create new instance of the payload Fire noMorePads. post error messages when something is wrong. No need to take streamLock, core does that now. * src/com/fluendo/plugin/JPEGDec.java: (JPEGDec.Pad): * src/com/fluendo/plugin/MulawDec.java: (MulawDec.Pad): * src/com/fluendo/plugin/SmokeDec.java: (SmokeDec.Pad): * src/com/fluendo/plugin/TheoraDec.java: (TheoraDec..Pad): * src/com/fluendo/plugin/VorbisDec.java: (VorbisDec..Pad): No need to take streamLock, core does that for us. * src/com/fluendo/plugin/AudioSinkJ2.java: (AudioSinkJ2.open): Post better error message. * src/com/fluendo/plugin/Queue.java: (Queue.Pad), (Queue): Stop flow on EOS. No need for streamLock. 2006-03-20 Thomas Vander Stichele * src/com/fluendo/examples/Player2.java: removed * src/com/fluendo/examples/Player3.java: renamed to Player.java 2006-03-20 Thomas Vander Stichele * README: update * build.xml: make sure that "all" target builds in order, so the examples work 2006-03-20 Wim Taymans * src/com/fluendo/jst/Clock.java: (Clock): Time are longs, avoids overflows. * src/com/fluendo/jst/Sink.java: (Sink.Pad): First pass at posting EOS. * src/com/fluendo/player/Cortado.java: (Cortado.handleMessage): Some more debugging about buffering and EOS. * src/com/fluendo/plugin/OggDemux.java: (OggDemux..OggStream.bufferFromPacket): Timestamp outgoing buffers. * src/com/fluendo/plugin/Queue.java: (Queue.updateBuffering), (Queue.Pad): Handle EOS when we are buffering. Fixes #247. * src/com/fluendo/plugin/TheoraDec.java: (TheoraDec..takeHeader), (TheoraDec..getFirstTs), (TheoraDec..Pad): Don't try to convert granulepos if we did not receive headers yet. 2006-03-20 Wim Taymans * TODO: Updated TODO. * src/com/fluendo/jst/Sink.java: (Sink.Pad): Set flushing flag correctly when we shutdown. * src/com/fluendo/plugin/AudioSink.java: (AudioSink.RingBuffer), (AudioSink.RingBuffer.acquire), (AudioSink.RingBuffer.setSample), (AudioSink.setCapsFunc), (AudioSink), (AudioSink.changeState): Fix race in going to paused. Don't deadlock when we try to release the audio device. 2006-02-28 Andy Wingo * TESTIMONIALS: New file, random testimonials culled from the mailing list. 2006-01-23 Wim Taymans * TODO: Updated TODO * src/com/fluendo/examples/Player2.java: (PlayPipeline.doSendEvent): Fix for API removal. * src/com/fluendo/jst/Buffer.java: (Buffer), (Buffer.create), (Buffer.Buffer): Added buffer flags. Prepare for using timestampEnd. * src/com/fluendo/jst/Event.java: (Event), Update newsegment event info to match GStreamer. (Event.parseSeekPosition), (Event.parseSeekFormat): * src/com/fluendo/jst/Pipeline.java: (Pipeline.doChildStateChange): Remove preroll hack. * src/com/fluendo/jst/Sink.java: (Sink), (Sink.Pad), (Sink.doSync), (Sink.query), (Sink.changeState): Remove preroll hack, parse segment info. Clip buffers outside of the segment. Handle DISCONT and clocking. * src/com/fluendo/plugin/AudioSink.java: (AudioSink.RingBuffer.commit), (AudioSink.doEvent): Clip around segments. * src/com/fluendo/plugin/HTTPSrc.java: (HTTPSrc), (HTTPSrc.Pad), (HTTPSrc.getInputStream): * src/com/fluendo/plugin/OggDemux.java: (OggDemux), (OggDemux..OggStream), (OggDemux..OggStream.OggStream), (OggDemux..OggStream.deActivate), (OggDemux..OggStream.reStart), (OggDemux..OggStream.getFirstTs), (OggDemux..OggStream.bufferFromPacket), (OggDemux..OggStream.pushPacket), (OggDemux..OggStream.pushPage), (OggDemux..OggStream.eventFunc), (OggDemux..OggStream.OggChain), (OggDemux..OggStream.OggChain.OggChain), (OggDemux..OggStream.OggChain.isActive), (OggDemux..OggStream.OggChain.activate), (OggDemux..OggStream.OggChain.deActivate), (OggDemux..OggStream.OggChain.reStart), (OggDemux..OggStream.OggChain.addStream), (OggDemux..OggStream.OggChain.markDiscont), (OggDemux..OggStream.OggChain.findStream), (OggDemux..OggStream.OggChain.resetStreams), (OggDemux..OggStream.OggChain.forwardEvent), (OggDemux..OggStream.OggChain.pushPage), (OggDemux..OggStream.Pad), (OggDemux..OggStream.getFactoryName), (OggDemux..OggStream.getMime), (OggDemux..OggStream.typeFind), (OggDemux..OggStream.OggDemux): Preroll sync and calc timestamps of payloads. Added preliminary support for chained oggs. Handle discont. * src/com/fluendo/plugin/OggPayload.java: Interface for payloads in ogg containers. * src/com/fluendo/plugin/TheoraDec.java: (TheoraDec..Pad), (TheoraDec.), (TheoraDec..TheoraDec), (TheoraDec..changeState), (TheoraDec..getFactoryName), (TheoraDec..getMime): * src/com/fluendo/plugin/VorbisDec.java: (VorbisDec), (VorbisDec..Pad), (VorbisDec.), (VorbisDec..VorbisDec), (VorbisDec..changeState), (VorbisDec..getFactoryName), (VorbisDec..getMime): Implement OggPayload. Handle discont. Remove timestamp hacks. 2006-01-20 Thomas Vander Stichele * build.xml: * src/com/fluendo/player/Cortado.java: (Cortado.init), (Cortado.stop): * src/com/fluendo/player/CortadoPipeline.java: (CortadoPipeline), (CortadoPipeline.build): * src/com/fluendo/plugin/AudioSinkSA.java: (AudioSinkSA): added an about dialog 2006-01-20 Thomas Vander Stichele * build.xml: add time of build as well, useful when debugging builds 2006-01-20 Wim Taymans * src/com/fluendo/plugin/AudioSinkSA.java: (AudioSinkSA...RingReader.read), (AudioSinkSA...RingReader.RingBufferSA.read): Change read behaviour to please both IE and jdk 2006-01-20 Wim Taymans * src/com/fluendo/jst/Pad.java: (Pad.setCaps): Don't call the listeners with null caps. * src/com/fluendo/plugin/AudioSinkSA.java: (AudioSinkSA...RingReader.stop): Some debugging 2006-01-20 Wim Taymans * src/com/fluendo/plugin/AudioSinkSA.java: (AudioSinkSA), (AudioSinkSA...toUlaw), (AudioSinkSA...RingReader.pause), (AudioSinkSA...RingReader.stop): Redid sun.audio backend to work on bytes and do more accurate resampling. 2006-01-20 Wim Taymans * src/com/fluendo/plugin/AudioSinkSA.java: (AudioSinkSA...RingReader.stop): Convert byte to int. 2006-01-20 Wim Taymans * src/com/fluendo/plugin/AudioSinkSA.java: (AudioSinkSA...RingReader), (AudioSinkSA...RingReader.RingReader), (AudioSinkSA...RingReader.pause), (AudioSinkSA...RingReader.stop), (AudioSinkSA...RingReader.read), (AudioSinkSA...RingReader.RingBufferSA.play), (AudioSinkSA...RingReader.RingBufferSA), (AudioSinkSA...RingReader.RingBufferSA.pause), (AudioSinkSA...RingReader.RingBufferSA.stop), (AudioSinkSA...RingReader.RingBufferSA.read): Implement read() for IE JVM. 2006-01-19 Wim Taymans * TODO: * src/com/fluendo/plugin/Queue.java: (Queue), (Queue.clearQueue), (Queue.Pad): Handle EOS gracefully. 2006-01-19 Thomas Vander Stichele * src/com/fluendo/jst/Bus.java: (Bus.peek): * src/com/fluendo/jst/Pipeline.java: (Pipeline.SortedEnumerator), (Pipeline.SortedEnumerator.queueNextElement): * src/com/fluendo/player/Status.java: * src/com/fluendo/plugin/Queue.java: (Queue.Pad): Fix Vector calls to work with 1.1 API - partially fixes applet in Explorer 2006-01-19 Wim Taymans * src/com/fluendo/plugin/AudioSinkSA.java: (AudioSinkSA...RingReader.stop): Print some errors when unimplemented methods are called. 2006-01-19 Wim Taymans * src/com/fluendo/player/Cortado.java: (Cortado.paint): Don't try to render with bogus width/height values. 2006-01-19 Thomas Vander Stichele * README: * TODO: update * build.xml: build non-jikes with correct debug as well 2006-01-19 Wim Taymans * src/com/fluendo/jst/Pipeline.java: (Pipeline.useClock), (Pipeline.add), (Pipeline), (Pipeline.remove): Don't accept null elements in add and remove. 2006-01-19 Wim Taymans * src/com/fluendo/player/Cortado.java: (Cortado), (Cortado.init), (Cortado.handleMessage): Cleanups. Pause pipeline while buffering. * src/com/fluendo/plugin/AudioSink.java: (AudioSink.RingBuffer.setSample), (AudioSink.RingBuffer.play), (AudioSink.RingBuffer.pause): * src/com/fluendo/plugin/AudioSinkJ2.java: Compile fixes. * src/com/fluendo/plugin/HTTPSrc.java: (HTTPSrc.Pad): Post stream status messages. * src/com/fluendo/plugin/Queue.java: (Queue.updateBuffering), (Queue.Pad): Never pause the stream when we are buffering so that we can preroll while buffering. 2006-01-19 Wim Taymans * src/com/fluendo/player/Cortado.java: (Cortado.stringToTime), (Cortado.handleMessage): Update buffering info. * src/com/fluendo/player/Status.java: (Status): Print buffering nicely. * src/com/fluendo/plugin/AudioSink.java: (AudioSink.RingBuffer.stop): * src/com/fluendo/plugin/AudioSinkSA.java: (AudioSinkSA), (AudioSinkSA...RingReader.RingBufferSA), (AudioSinkSA...RingReader.RingBufferSA.startWriteThread), (AudioSinkSA...RingReader.open), (AudioSinkSA...RingReader.write): Some cleanups. 2006-01-19 Wim Taymans * src/com/fluendo/player/CortadoPipeline.java: (CortadoPipeline.build): Autodetect audio backend. * src/com/fluendo/plugin/AudioSinkSA.java: (AudioSinkSA...RingReader.createRingBuffer), (AudioSinkSA...RingReader.write): Fix sync in sun.audio backend. 2006-01-19 Wim Taymans * src/com/fluendo/plugin/AudioSink.java: (AudioSink), (AudioSink.AudioClock.getInternalTime), (AudioSink.RingBuffer.run), (AudioSink.RingBuffer.acquire), (AudioSink.RingBuffer.samplesPlayed), (AudioSink.doEvent): * src/com/fluendo/plugin/AudioSinkJ2.java: (AudioSinkJ2), (AudioSinkJ2.open), (AudioSinkJ2.close): * src/com/fluendo/plugin/AudioSinkSA.java: * src/com/fluendo/plugin/HTTPSrc.java: (HTTPSrc.getInputStream): * src/com/fluendo/plugin/MultipartDemux.java: * src/com/fluendo/plugin/OggDemux.java: (OggDemux.Pad): * src/com/fluendo/plugin/Queue.java: Code cleanups. Remove unused vars. Calculate delay more accurately in javax.sound backend. Don't set caps on HTTPSrc when already set. 2006-01-19 Wim Taymans * src/com/fluendo/examples/Player2.java: * src/com/fluendo/examples/Player3.java: * src/com/fluendo/player/Cortado.java: * src/com/fluendo/player/CortadoPipeline.java: (CortadoPipeline.build): * src/com/fluendo/player/Status.java: Code reformatting and cleanups. 2006-01-19 Wim Taymans * src/com/fluendo/jst/Buffer.java: (Buffer.ensureSize): * src/com/fluendo/jst/Pad.java: (Pad): * src/com/fluendo/jst/Pipeline.java: (Pipeline): Remove unused vars. 2006-01-19 Wim Taymans * src/com/fluendo/codecs/SmokeCodec.java: (SmokeCodec), (SmokeCodec.parseHeader): Fix unused vars. 2006-01-19 Wim Taymans * src/com/fluendo/jheora/Colorspace.java: * src/com/fluendo/jheora/DCTDecode.java: (DCTDecode.....ReconRefFrames): * src/com/fluendo/jheora/Decode.java: * src/com/fluendo/jheora/Filter.java: (Filter..LoopFilter): * src/com/fluendo/jheora/JTheoraException.java: * src/com/fluendo/jheora/Playback.java: * src/com/fluendo/jheora/Quant.java: Remove lots of unused vars 2006-01-18 Thomas Vander Stichele * build.xml: compile is now a virtual target 2006-01-18 Thomas Vander Stichele * HACKING: expand on the file layout * src/com/fluendo/examples/OggPerf.java: * src/com/fluendo/examples/OggTheoraPerf.java: * src/com/fluendo/examples/Player2.java: * src/com/fluendo/examples/Player3.java: * src/com/fluendo/jst/Sink.java: * src/com/fluendo/plugin/VideoSink.java: more build cleanups 2006-01-18 Thomas Vander Stichele * build.xml: remove plugins.ini rule invoke includes rule for applet builds and compile-examples 2006-01-18 Thomas Vander Stichele * build.xml: fix up various build issues; can now run the Player2 example with java --cp output/build/debug com.fluendo.examples.Player2 http://stream.fluendo.com:8800 2006-01-18 Thomas Vander Stichele * build.xml: various build fixes so that plugins are correctly found add compile-examples 2006-01-18 Thomas Vander Stichele * build.properties: * build.xml: various cleanups for the build * src/com/fluendo/jst/Pipeline.java: * src/com/fluendo/jst/Sink.java: * src/com/fluendo/plugin/Sink.java: move Sink.java to jst, as it's used in Pipeline 2006-01-18 Thomas Vander Stichele * build.config.sample: add a sample build.config file to customize * build.xml: fix up clean rule add more jars 2006-01-18 Thomas Vander Stichele * Makefile: * build.xml: * gen-Configure: remove gen-Configure; implement it in ant; output during build 2006-01-18 Thomas Vander Stichele * build.xml: split out more of the jars and compiles 2006-01-18 Thomas Vander Stichele * build.xml: always include stubs in classpath for now; see what this does with the Sun compiler * src/com/fluendo/jst/Element.java: * src/com/fluendo/plugin/AudioSink.java: remove unneeded imports 2006-01-17 Thomas Vander Stichele * build.xml: clean up rules further set out.build to a build-type-specific location for all rules add applet and jar rules that build all of them add debug and release targets 2006-01-17 Thomas Vander Stichele * HACKING: * Makefile: * build.properties: * build.xml: allow for debug and release builds various cleanups, learnt about ant -projecthelp, looks nice now 2006-01-17 Thomas Vander Stichele * src/com/fluendo/jst/Element.java: (Element): * src/com/fluendo/jst/Object.java: (Object): * src/com/fluendo/jst/Pad.java: (Pad): * src/com/fluendo/jst/Pipeline.java: (Pipeline), (Pipeline.SortedEnumerator.updateDegree): * src/com/fluendo/plugin/Sink.java: (Sink.changeState): further compile cleanups 2006-01-17 Thomas Vander Stichele * build.xml: make compile-jcraft and jar-jcraft targets and shut up warnings for them 2006-01-17 Thomas Vander Stichele * src/com/fluendo/codecs/SmokeCodec.java: (SmokeCodec): * src/com/fluendo/jheora/DCTDecode.java: (DCTDecode.....UpdateUMV_HBorders): * src/com/fluendo/jheora/Info.java: (Info._tp_readlsbint): * src/com/fluendo/jheora/iDCT.java: (iDCT.IDct10): * src/com/fluendo/jst/Element.java: (Element.getPad): * src/com/fluendo/jst/Pad.java: (Pad.doCapsListeners): * src/com/fluendo/jst/Pipeline.java: (Pipeline.doChildStateChange): * src/com/fluendo/player/CortadoPipeline.java: (CortadoPipeline): remove unused vars 2006-01-17 Thomas Vander Stichele * build.properties: * src/com/fluendo/codecs/SmokeCodec.java: * src/com/fluendo/jheora/DCTDecode.java: * src/com/fluendo/jheora/Info.java: * src/com/fluendo/jheora/YUVBuffer.java: * src/com/fluendo/jst/Element.java: * src/com/fluendo/jst/Event.java: * src/com/fluendo/jst/Message.java: * src/com/fluendo/jst/Pipeline.java: * src/com/fluendo/jst/Query.java: * src/com/fluendo/player/Cortado.java: * src/com/fluendo/player/CortadoPipeline.java: * src/com/fluendo/player/Status.java: * src/com/fluendo/plugin/JPEGDec.java: * src/com/fluendo/plugin/Sink.java: * src/com/fluendo/plugin/SmokeDec.java: * src/com/fluendo/plugin/TheoraDec.java: remove unneeded imports 2006-01-17 Thomas Vander Stichele * merged "build" branch: svn merge -r 2703:HEAD branches/build/ trunk/ 2006-01-17 Thomas Vander Stichele * Makefile: * build.properties: * build.xml: add build.properties merge sun and jikes build in one, should now be adaptable to all compilers 2006-01-17 Thomas Vander Stichele * Makefile: * build.xml: * HACKING: reorganize build further. "make ovt" and "make mmjs" seem to produce applets. add HACING notes 2006-01-16 Thomas Vander Stichele * custom/mp-jpeg.sh: * custom/theora-ogg.sh: remove old custom scripts 2006-01-10 Wim Taymans * com/fluendo/player/CortadoPipeline.java: (CortadoPipeline.build): Enable sun.audio backend. * com/fluendo/plugin/AudioSink.java: (AudioSink.provideClock), (AudioSink.RingBuffer.run), (AudioSink.RingBuffer.setFlushing), (AudioSink.RingBuffer.startWriteThread), (AudioSink.RingBuffer), (AudioSink.RingBuffer.acquire), (AudioSink.RingBuffer.release), (AudioSink.RingBuffer.waitSegment), (AudioSink.RingBuffer.commit), (AudioSink.RingBuffer.samplesPlayed): Make fields protected. Abstract the reader thread. * com/fluendo/plugin/AudioSinkSA.java: * plugins.ini: Added sun.audio backend. 2006-01-09 Wim Taymans * com/fluendo/jst/Caps.java: (Caps), (Caps.Caps), (Caps.toString), (Caps.setField), (Caps.setFieldInt), (Caps.getField), (Caps.getFieldInt): Parse extra properties on caps. * com/fluendo/jst/CapsListener.java: Added capslistener. * com/fluendo/jst/Pad.java: (Pad), (Pad.Pad), (Pad.toString), (Pad.query), (Pad.getCaps), (Pad.setCapsFunc), (Pad.setCaps): Notify capslisteners when caps changed. * com/fluendo/player/CortadoPipeline.java: (CortadoPipeline.padAdded), (CortadoPipeline.getComponent), (CortadoPipeline), (CortadoPipeline.setBufferSize), (CortadoPipeline.getBufferSize), (CortadoPipeline.setBufferLow), (CortadoPipeline.getBufferLow), (CortadoPipeline.setBufferHigh), (CortadoPipeline.getBufferHigh), (CortadoPipeline.buildOgg), (CortadoPipeline.build): Autoplug based on mime type. * com/fluendo/player/Status.java: Don't show unknown position values. * com/fluendo/plugin/HTTPSrc.java: (HTTPSrc), (HTTPSrc.Pad), (HTTPSrc.getInputStream): Parse mimetype and set as caps on the buffers and pad. * com/fluendo/plugin/MultipartDemux.java: (MultipartDemux.MultipartStream), (MultipartDemux), (MultipartDemux.Pad), (MultipartDemux.getFactoryName): Parse input caps and use caps boundary string field. 2006-01-09 Wim Taymans * com/fluendo/jst/ElementFactory.java: Fix deprecated method. * com/fluendo/jst/Pipeline.java: (Pipeline.calcPrerollTime): Max/min syncOffset handling. * com/fluendo/plugin/AudioSink.java: (AudioSink.RingBuffer.stop), (AudioSink.render): * com/fluendo/plugin/Sink.java: (Sink.Pad), (Sink), (Sink.preroll), (Sink.doEvent): Don't render buffers before the syncOffset. * com/fluendo/plugin/HTTPSrc.java: (HTTPSrc.Pad): Remove debug. 2006-01-05 Wim Taymans * com/fluendo/examples/Player3.java: (Player3.Player3): New testcase. * com/fluendo/jst/ElementFactory.java: Print real element names. * com/fluendo/jst/Pipeline.java: (Pipeline.calcPrerollTime), (Pipeline.changeState): Remove debugging. * com/fluendo/player/Cortado.java: (Cortado.handleMessage): More debugging. * com/fluendo/plugin/AudioSink.java: (AudioSink.RingBuffer.acquire), (AudioSink.RingBuffer.commit), (AudioSink.RingBuffer), (AudioSink.RingBuffer.samplesPlayed): * com/fluendo/plugin/AudioSinkJ2.java: (AudioSinkJ2.open): Make sure we have at least 4 segments to work with. Detect disconts. * com/fluendo/plugin/Sink.java: (Sink.doSync): Small cleanups. 2006-01-05 Wim Taymans * com/fluendo/jst/Clock.java: (Clock): * com/fluendo/player/Cortado.java: (Cortado.handleMessage): Small cleanups. * com/fluendo/jst/Element.java: (Element.getMime): An element must provide a factoryName. * com/fluendo/jst/ElementFactory.java: Allow setting custom element names. * com/fluendo/jst/Message.java: (Message.toString), (Message.newStateDirty): More info in stream status messages. * com/fluendo/jst/Pad.java: (Pad.isFlowFatal): Make flowname usable by other classes. * com/fluendo/jst/Pipeline.java: (Pipeline.Pipeline), (Pipeline.calcPrerollTime), (Pipeline), (Pipeline.changeState): Calc syncOffset and distribute after a seek. * com/fluendo/examples/Player2.java: (PlayPipeline): * com/fluendo/player/CortadoPipeline.java: (CortadoPipeline), (CortadoPipeline.buildOgg), (CortadoPipeline.build): Name elements properly. * com/fluendo/plugin/AudioSink.java: (AudioSink.AudioClock), (AudioSink.AudioClock.getInternalTime), (AudioSink.RingBuffer.commit), (AudioSink.RingBuffer.samplesPlayed), (AudioSink.RingBuffer), (AudioSink.RingBuffer.clear), (AudioSink.RingBuffer.clearAll), (AudioSink.RingBuffer.setSample), (AudioSink.RingBuffer.play), (AudioSink.RingBuffer.pause), (AudioSink.doEvent), (AudioSink), (AudioSink.render), (AudioSink.setCapsFunc), (AudioSink.changeState): * com/fluendo/plugin/AudioSinkJ2.java: (AudioSinkJ2): * com/fluendo/plugin/FakeSink.java: (FakeSink.render): * com/fluendo/plugin/HTTPSrc.java: (HTTPSrc.Pad), (HTTPSrc.getInputStream): * com/fluendo/plugin/JPEGDec.java: (JPEGDec.getProperty): * com/fluendo/plugin/MulawDec.java: (MulawDec.MulawDec): * com/fluendo/plugin/MultipartDemux.java: (MultipartDemux.Pad): * com/fluendo/plugin/OggDemux.java: (OggDemux.Pad): * com/fluendo/plugin/Queue.java: (Queue.updateBuffering), (Queue), (Queue.start), (Queue.Pad), (Queue.Queue): * com/fluendo/plugin/Sink.java: (Sink), (Sink.getPrerollTime), (Sink.Pad), (Sink.doSync), (Sink.query), (Sink.changeState): * com/fluendo/plugin/SmokeDec.java: (SmokeDec.getProperty): * com/fluendo/plugin/TheoraDec.java: (TheoraDec.changeState): * com/fluendo/plugin/VideoSink.java: (VideoSink.render): * com/fluendo/plugin/VorbisDec.java: (VorbisDec.changeState): Fix factory names. Remove ringbuffer sync hack. Preroll and syncOffset implemented in Sink. Post stream status. Don't run the clock when we are paused in the audiosink. 2006-01-04 Wim Taymans * Makefile: Some updates. Compile with deprecation warnings. * com/fluendo/player/CortadoPipeline.java: (CortadoPipeline.padAdded), (CortadoPipeline.buildOgg), (CortadoPipeline.buildMultipartJPEG), (CortadoPipeline.buildMultipartSmoke), (CortadoPipeline), (CortadoPipeline.build): Added Smoke pipeline, * com/fluendo/plugin/MultipartDemux.java: (MultipartDemux.Pad): Small cleanup. * com/fluendo/plugin/SmokeDec.java: (SmokeDec.Pad), (SmokeDec), (SmokeDec.SmokeDec): Add property to configure component. * com/fluendo/plugin/VideoSink.java: (VideoSink.setCapsFunc): Replace deprecated method. * plugins.ini: Add smoke plugins to registry. 2005-12-21 Wim Taymans * com/fluendo/examples/Player3.java: (Player3.Player3): Enable multipart. * com/fluendo/jst/Pad.java: (Pad): Return NOT_LINKED when there is no peer. * com/fluendo/player/CortadoPipeline.java: (CortadoPipeline), (CortadoPipeline.padAdded), (CortadoPipeline.setBufferHigh), (CortadoPipeline.getBufferHigh), (CortadoPipeline.buildOgg), (CortadoPipeline.buildMultipart), (CortadoPipeline.build): Check for null caps. Add multipart jpeg pipelines, * com/fluendo/plugin/JPEGDec.java: (JPEGDec), (JPEGDec.Pad), (JPEGDec.JPEGDec), (JPEGDec.changeState): Send images downstream after we created them in the media tracker. * com/fluendo/plugin/MulawDec.java: (MulawDec), (MulawDec.Pad), (MulawDec.MulawDec): Make variable names java-like. * com/fluendo/plugin/MultipartDemux.java: (MultipartDemux), (MultipartDemux.MultipartStream), (MultipartDemux.MultipartStream.MultipartStream), (MultipartDemux.MultipartStream.eventFunc), (MultipartDemux.Pad), (MultipartDemux.getName), (MultipartDemux.getMime), (MultipartDemux.typeFind), (MultipartDemux.MultipartDemux): Implement the multipart demuxer. 2005-12-20 Wim Taymans * com/fluendo/jst/Event.java: (Event.newSeek), (Event.newNewsegment): Make method names consistent as in Query/Message. * com/fluendo/jst/Pipeline.java: (Pipeline.doChildStateChange), (Pipeline.calcPrerollTime), (Pipeline), (Pipeline.changeState), (Pipeline.doSendEvent), (Pipeline.doSeek), (Pipeline.sendEvent), (Pipeline.query): Do correct preroll time distribution in pipeline. * com/fluendo/player/Cortado.java: (Cortado.newState), (Cortado.newSeek): Warn when seek failed. * com/fluendo/player/CortadoPipeline.java: The pipeline used by the applet. * com/fluendo/player/StatusListener.java: Get info on actions performed in the Status area. * com/fluendo/plugin/JPEGDec.java: * com/fluendo/plugin/MulawDec.java: * com/fluendo/plugin/MultipartDemux.java: * com/fluendo/plugin/SmokeDec.java: * plugins.ini: New plugins added. * com/fluendo/plugin/HTTPSrc.java: (HTTPSrc.Pad): * com/fluendo/plugin/Sink.java: (Sink.Pad): Update for name change. 2005-12-19 Wim Taymans * README: Add some new params to docs. * com/fluendo/examples/Player2.java: (PlayPipeline.PlayPipeline): * com/fluendo/examples/Player3.java: Added player that instantiates the Cortado applet. * com/fluendo/jst/Element.java: (Element.getState): the timeout for wait is in milliseconds, make correct conversion from gst time. * com/fluendo/jst/Message.java: (Message), (Message.toString), (Message.newError), (Message.parseErrorString): Added buffering message. * com/fluendo/player/Cortado.java: (Cortado), (Cortado.getParameterInfo), (Cortado.init), (Cortado.paint), (Cortado.handleMessage), (Cortado.newState), (Cortado.newSeek), (Cortado.start), (Cortado.stop): Added buffering. * com/fluendo/player/Status.java: Print buffering percent. * com/fluendo/plugin/HTTPSrc.java: (HTTPSrc.Pad): Small debug updates. Don't try to use a null inputstream. * com/fluendo/plugin/Queue.java: (Queue), (Queue.isFilled), (Queue.isEmpty), (Queue.clearQueue), (Queue.updateBuffering), (Queue.start), (Queue.stop), (Queue.Pad), (Queue.Queue), (Queue.getName): Added buffering to queue. 2005-12-19 Wim Taymans * com/fluendo/jst/Pad.java: (Pad.run), (Pad.startTask): Make method public. * com/fluendo/jst/Queue.java: * com/fluendo/plugin/Queue.java: * plugins.ini: Move queue to plugins. 2005-12-19 Wim Taymans * com/fluendo/jst/Element.java: (Element.sendEvent): Added query method. * com/fluendo/jst/Pad.java: (Pad.unlink), (Pad.sendEvent): Add query and getpeer methods. * com/fluendo/jst/Pipeline.java: (Pipeline.sendEvent): Forward queries to the sinks, * com/fluendo/jst/Query.java: (Query.newPosition), (Query.parsePositionValue), (Query), (Query.newDuration): Implement setting query result. * com/fluendo/player/Cortado.java: (Cortado), (Cortado.getParameterInfo), (Cortado.shutdown), (Cortado.stringToTime), (Cortado.init), (Cortado.getGraphics), (Cortado.getSize), (Cortado.update), (Cortado.run), (Cortado.realRun), (Cortado.newState), (Cortado.newSeek), (Cortado.start): Added option to configure the duration. start thread to update current position in statusbar. * com/fluendo/player/Status.java: Paint current position in time. * com/fluendo/plugin/Sink.java: (Sink.sendEvent): Implement POSITION query. 2005-12-15 Wim Taymans * com/fluendo/jst/Pipeline.java: (Pipeline.doSeek): A seek sets the stream time to 0 since we always do flushing seeks. * com/fluendo/jst/Queue.java: (Queue.Pad): Fix nasty deadlock. * com/fluendo/player/Configure.java: * com/fluendo/player/Cortado.java: (Cortado), (Cortado.init), (Cortado.setStatusVisible), (Cortado.mouseClicked), (Cortado.mouseEntered), (Cortado.mouseExited), (Cortado.mousePressed), (Cortado.mouseReleased), (Cortado.mouseDragged), (Cortado.mouseMoved), (Cortado.handleMessage), (Cortado.newState): Forward dragging events in the status area. React to seek signals. Try not to hide the statusbar when the pointer is in it. * com/fluendo/player/Status.java: (Status): Refactor painting a bit. Implement seek bar and make it emit a newSeek signal. * com/fluendo/plugin/AudioSink.java: (AudioSink.RingBuffer.commit), (AudioSink.RingBuffer.samplesPlayed), (AudioSink.render), (AudioSink.changeState): Do timestamp calc. * com/fluendo/plugin/AudioSinkJ2.java: (AudioSinkJ2.createRingBuffer): Reenable syncing. * com/fluendo/plugin/HTTPSrc.java: (HTTPSrc.Pad), (HTTPSrc), (HTTPSrc.getInputStream): * com/fluendo/plugin/OggDemux.java: (OggDemux.Pad): * com/fluendo/plugin/TheoraDec.java: (TheoraDec.Pad): Nicer debug and error messages. * com/fluendo/plugin/Sink.java: (Sink), (Sink.Pad), (Sink.doEvent), (Sink.doSync), (Sink.changeState): Calc correct timestamps based on prerolled time and basetime. 2005-12-15 Wim Taymans * com/fluendo/jst/Pad.java: (Pad.setCapsFunc), (Pad.activate): Allow setting null caps. * com/fluendo/jst/Queue.java: (Queue.Pad): Properly shut down the queue, avoid deadlock. * com/fluendo/player/Configure.java: * com/fluendo/player/Cortado.java: (Cortado.handleMessage): Also print errors and stream status to console. * com/fluendo/player/Status.java: Allow setting playing state when in stopped. * com/fluendo/plugin/AudioSink.java: (AudioSink), (AudioSink.AudioClock.getInternalTime), (AudioSink.RingBuffer), (AudioSink.RingBuffer.run), (AudioSink.RingBuffer.samplesPlayed), (AudioSink.RingBuffer.play), (AudioSink.RingBuffer.pause), (AudioSink.changeState): Allow shutdown. * com/fluendo/plugin/AudioSinkJ2.java: (AudioSinkJ2.createRingBuffer): Remove temp hack. * com/fluendo/plugin/HTTPSrc.java: (HTTPSrc.Pad): Remove stupid print. * com/fluendo/plugin/OggDemux.java: (OggDemux.Pad): Do proper shutdown. * com/fluendo/plugin/Sink.java: (Sink.Pad), (Sink.changeState): * com/fluendo/plugin/TheoraDec.java: (TheoraDec), (TheoraDec.Pad), (TheoraDec.TheoraDec): * com/fluendo/plugin/VorbisDec.java: (VorbisDec), (VorbisDec.Pad), (VorbisDec.VorbisDec): Fix shutdown. 2005-12-14 Wim Taymans * Makefile: Added some targets. * com/fluendo/jst/Clock.java: (Clock.ClockID.waitID): No need to check for unscheduled here, it'll be done in the waitFunc. * com/fluendo/jst/Element.java: (Element.getTransitionNext), (Element.continueState), (Element.changeState), (Element), (Element.doChangeState): Bring state changes up to data with GStreamer core. Fix race condition that probably also exist in GST when we update the lastReturn right after the element commited state ASYNC. * com/fluendo/jst/Pad.java: (Pad.isFlowFatal): Added debugging function * com/fluendo/jst/Pipeline.java: (Pipeline.StateThread.run), (Pipeline.reCalcState): Use new API to continue state change. * com/fluendo/jst/Query.java: (Query), (Query.newPosition), (Query.newDuration): Fix compilation * com/fluendo/jst/Queue.java: (Queue.Pad): Better debugging. Don't post an error when we did not cause the error but instead post a stream-status message to notify that we stopped streaming. * com/fluendo/player/Configure.java: * com/fluendo/player/Cortado.java: * com/fluendo/player/CortadoPipeline.java: * com/fluendo/player/Status.java: New Applet using JST along with JST pipelines and gui. * com/fluendo/plugin/AudioSink.java: (AudioSink.render), (AudioSink.changeState): * com/fluendo/plugin/Sink.java: (Sink.Pad), (Sink.changeState): Update to latest GST base classes. * com/fluendo/plugin/AudioSinkJ2.java: (AudioSinkJ2.open): Post error when we cannot open the device. * com/fluendo/plugin/HTTPSrc.java: (HTTPSrc.Pad), (HTTPSrc), (HTTPSrc.getInputStream): Better error handling. * com/fluendo/plugin/VideoSink.java: (VideoSink), (VideoSink.setCapsFunc), (VideoSink.preroll), (VideoSink.render), (VideoSink.getName): Make videosink work with foreign Components. * com/fluendo/plugin/VorbisDec.java: (VorbisDec.Pad): Forward flow errors. 2005-11-07 Wim Taymans * com/fluendo/examples/Player2.java: (PlayPipeline), (PlayPipeline.padRemoved), (PlayPipeline.noMorePads), (Player2), (Player2.handleMessage): Fix player to handle any uri. * com/fluendo/jst/ElementFactory.java: Added typefind. * com/fluendo/jst/Pad.java: (Pad.sendEvent), (Pad.chain): Handle setCaps(). * com/fluendo/plugin/OggDemux.java: (OggDemux.OggStream), (OggDemux.OggStream.OggStream), (OggDemux.Pad): Set caps. * com/fluendo/plugin/AudioSink.java: (AudioSink.render): * com/fluendo/plugin/Sink.java: (Sink.Pad), (Sink.doSync): * com/fluendo/plugin/VideoSink.java: (VideoSink): Handle new caps. 2005-11-04 Wim Taymans * com/fluendo/jst/Query.java: Added Query API. 2005-11-04 Wim Taymans * com/fluendo/examples/Player2.java: (PlayPipeline.PlayPipeline), (PlayPipeline.doSendEvent): Simplified after changes in the core. * com/fluendo/jst/Element.java: (Element.getTransitionNext), (Element.commitState), (Element.doChangeState), (Element.setState): Propagate state change return values to the caller. * com/fluendo/jst/Format.java: (Format): Implement PERCENT format constants. * com/fluendo/jst/Pad.java: (Pad): Added isFlowFatal(). * com/fluendo/jst/Pipeline.java: (Pipeline.reCalcState), (Pipeline.doChildStateChange), (Pipeline.changeState): State change updates. Send events to all sinks by default. * com/fluendo/jst/Queue.java: (Queue), (Queue.isFilled), (Queue.isEmpty), (Queue.clearQueue), (Queue.Pad): Updates to queue to make it flush faster. Fix refcounting of buffers when clearing the queue. * com/fluendo/player/Configure.java: * com/fluendo/plugin/AudioSink.java: (AudioSink.RingBuffer), (AudioSink.RingBuffer.run), (AudioSink.RingBuffer.release), (AudioSink.RingBuffer.waitSegment), (AudioSink.RingBuffer.samplesPlayed), (AudioSink.RingBuffer.clear), (AudioSink.RingBuffer.clearAll), (AudioSink.RingBuffer.setSample), (AudioSink.RingBuffer.stop), (AudioSink), (AudioSink.doSync), (AudioSink.doEvent): Added setFlushing so that we never enter a blocking call again. * com/fluendo/plugin/HTTPSrc.java: (HTTPSrc), (HTTPSrc.Pad), (HTTPSrc.getInputStream), (HTTPSrc.getName), (HTTPSrc.HTTPSrc), (HTTPSrc.setProperty): Get Content-Length from HTTP response header to get the length of the file. Implement percent seeking. Added property to configure readSize. * com/fluendo/plugin/OggDemux.java: (OggDemux.Pad): Add proper locks around event handling code. * com/fluendo/plugin/Sink.java: (Sink.Sink): Implement sendEvent. * com/fluendo/plugin/TheoraDec.java: (TheoraDec.Pad): * com/fluendo/plugin/VorbisDec.java: (VorbisDec.Pad): Take proper locks around event handling code. free buffers when clearing the queued buffers. 2005-11-03 Wim Taymans * Makefile: * com/fluendo/examples/Player.java: * com/fluendo/examples/Player2.java: (PlayPipeline), (PlayPipeline.PlayPipeline): * com/fluendo/jst/Element.java: (Element), (Element.typeFind), (Element.Element), (Element.setComponent), (Element.setClock), (Element.getClock), (Element.getBus), (Element.addPadListener), (Element.removePadListener), (Element.doPadListeners), (Element.addPad), (Element.removePad), (Element.noMorePads), (Element.getState), (Element.padsActivate), (Element.commitState), (Element.abortState), (Element.lostState), (Element.changeState): * com/fluendo/jst/Event.java: (Event), (Event.newFlushStart), (Event.getSeekFormat): * com/fluendo/jst/Object.java: (Object), (Object.getParent), (Object.unParent): * com/fluendo/jst/Pad.java: (Pad), (Pad.eventFunc), (Pad.sendEvent), (Pad.configureSink), (Pad.chain): * com/fluendo/jst/PadListener.java: * com/fluendo/jst/Pipeline.java: (Pipeline.BusThread), (Pipeline.BusThread.BusThread), (Pipeline.BusThread.run), (Pipeline.BusThread.shutDown), (Pipeline), (Pipeline.StateThread), (Pipeline.StateThread.StateThread), (Pipeline.StateThread.run), (Pipeline.StateThread.stateDirty), (Pipeline.Pipeline), (Pipeline.useClock): * com/fluendo/jst/Queue.java: (Queue.Pad): * com/fluendo/player/Buffer.java: * com/fluendo/player/Caps.java: * com/fluendo/player/Clock.java: * com/fluendo/player/ClockProvider.java: * com/fluendo/player/Configure.java: * com/fluendo/player/Element.java: * com/fluendo/player/ElementFactory.java: * com/fluendo/player/Event.java: * com/fluendo/player/Format.java: * com/fluendo/player/Object.java: * com/fluendo/player/Pad.java: * com/fluendo/player/PadListener.java: * com/fluendo/player/Pipeline.java: * com/fluendo/player/Queue.java: * com/fluendo/player/SystemClock.java: * com/fluendo/plugin/AudioSink.java: (AudioSink.RingBuffer.commit), (AudioSink.RingBuffer.stop), (AudioSink.doEvent), (AudioSink.render), (AudioSink.setCaps), (AudioSink.changeState): * com/fluendo/plugin/HTTPSrc.java: (HTTPSrc.Pad), (HTTPSrc.getInputStream): * com/fluendo/plugin/OggDemux.java: (OggDemux.Pad): * com/fluendo/plugin/Sink.java: (Sink), (Sink.Pad), (Sink.preroll), (Sink.doEvent), (Sink.doSync), (Sink.setCaps), (Sink.render), (Sink.Sink), (Sink.changeState): * com/fluendo/plugin/TheoraDec.java: (TheoraDec.Pad): * com/fluendo/plugin/VideoSink.java: (VideoSink.getProperty): * com/fluendo/plugin/VorbisDec.java: (VorbisDec.Pad): Updated jst to match latest GStreamer core, updated examples, implemented bus, messages. Fix deadlocks while seeking. Implemented state changes with topologocal sort. === release 0.1.2 === 2005-04-22 Thomas Vander Stichele * Makefile: * build.xml: * gen-Configure: do some more versioning 2005-04-22 Wim Taymans make multiple instances of cortado work correctly 2004-12-24 Thomas Vander Stichele * Makefile: bump nano === release 0.1.0 === 2004-12-24 Thomas Vander Stichele * Makefile: * README: more notes and fixes 2004-12-24 Thomas Vander Stichele * Makefile: * README: * build.xml: updates for public release === release 0.0.1 === 2004-11-30 Thomas Vander Stichele * Makefile: * build.xml: add targets for two kinds of applets and version * stubs/sun/audio/AudioPlayer.java: * stubs/sun/audio/AudioStream.java: Fix stubs by decompiling the sun java class files 2004-11-19 Thomas Vander Stichele * com/fluendo/player/Cortado.java: fix compiler warning 2004-11-19 Thomas Vander Stichele * build.xml: allow excluding functionality with -Dexclude=(which,...) 2004-11-19 Thomas Vander Stichele reviewed by: Wim Taymans * com/fluendo/player/Cortado.java: * com/fluendo/player/Status.java: Replace getWidth and getHeight with getSize (1.1) cortado-0.6.0/HACKING100644 0 0 4747 11270111317 11274 0ustar 0 0 HACKING NOTES for Cortado ------------------------- directory layout: - src: source code - com/jcraft: copy of JCraft JOgg and Jorbis source code, plus some changes - com/fluendo: Source code written by Fluendo - utils: utitity classes used by jst, jheora, examples - jst: a java port of the GStreamer 0.10 design - jheora: a java implementation of the Theora video codec - jkate: a basic java implementation of the Kate codec - jtiger: a basic Kate stream renderer (simple text/images only for now) - codecs: additional codecs; currently contains the Smoke codec - plugin: plugins implementing/wrapping sources/decoders/sinks - examples: example programs - stubs: stubs that contain minimal definitions for other classes to allow compilation - sun/audio: stubs for sun.audio.* - javax/sound: - sampled: stubs for javax.sound.sampled.* - output: files generated as part of the build - build: built class files - debug: debug build - release: release build - dist: resulting jar files - debug: debug versions of all cortado .jars - release: release versions of all cortado .jars - applets: all applet jars - src: source distributions NOTES ----- - from the ant build file, we should be able to: - make a tarball with all the source and build stuff: "ant dist" (done) - generate the separate jars "ant jar-jcraft ..." - build the examples - generate stripped and debug versions of the applets, with specific plugins included "ant applets" or "ant applet-ovt applet-mmjs" "ant applets-debug" - the plan is to: - build com.fluendo.utils in a jar - build com.jcraft in a jar - build com.fluendo.jheora in a jar (relying on jcraft and utils jars) - build com.fluendo.jst in a jar (relying on utils) - build com.fluendo.plugin into a jar (all combined, relying on all above) - FIXME: what to do with the examples ? HISTORY ------ - applet sizes: - cortado ovt debug: - 2006-05-19: 259354 bytes - cortado ovt stripped: - 0.1.2.1, 2005-04-29: 179327 bytes - 0.1.2.1, 2006-01-17: 191901 bytes (after JST implementation) - 0.2.0, 2006-05-19: 189596 bytes - 0.2.2, 2006-10-26: 198094 bytes RELEASING --------- moap doap -v 0.2.2 mail -f thomas@fluendo.com thomas@apestaart.org moap doap -v 0.2.2 mail -f thomas@apestaart.org theora@xiph.org cortado-0.6.0/LICENSE.cortado100644 0 0 1426 11270111317 12733 0ustar 0 0 /* Cortado - a video player java applet * Copyright (C) 2004 Fluendo S.L. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. */ cortado-0.6.0/LICENSE.jheora100644 0 0 1703 11270111317 12546 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ cortado-0.6.0/LICENSE.jkate100644 0 0 1553 11270111317 12377 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ cortado-0.6.0/LICENSE.jtiger100644 0 0 1555 11270111317 12567 0ustar 0 0 /* JTiger * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JTiger are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ cortado-0.6.0/LICENSE.smoke100644 0 0 1461 11270111317 12415 0ustar 0 0 /* Smoke Codec * Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ cortado-0.6.0/NEWS100644 0 0 7305 11350736701 11006 0ustar 0 0 This is Cortado 0.6.0, "Increasing increase" Changes since 0.5.2 * support for Theora files with 4:4:4 and 4:2:2 sampling * Reinforced compatibility with Java 1.1 * Improved support for videos with dropped frames * Much improved support for Kate subtitles (including menu to select subtitle stream) * More robust scanning for stream duration * Fixed Vorbis surround sound * Release binaries should export a subset of the HTML5 media API again Changes since 0.5.1 * make keepAspect ignorable again * minor optimizations in the decoder * buffer tweaks to prevent unwanted frame drops * contents of plugins.ini moved into code to work around resource-loading problems in ancient JVMs * fix problems with several audio streams * optimizations in YUV-to-RGB code Changes since 0.5.0: * Fix for ticket #1565: Cortado doesn't handle incomplete packets correctly. * On very slow machines that can't handle video in realtime, completely skip decoding of inter frames and process keyframes only to ensure smooth audio decoding. * Improved support for older VMs. Changes since 0.2.2: * Support for files encoded with Theora 1.1 * Faster YUV to RGB conversion with better results * Correct a bug in the iDCT10 implementation * Basic support for embedded Ogg Kate streams * Seeking fixed for files with an Ogg Skeleton track * Maintained compatibility with the Microsoft VM Changes since 0.2.1: * add statusHeight property * add autoPlay property * add documentBase property * add showStatus property * add hideTimeout property * add JavaScript methods * seek slider is easier to manipulate * framerate property is removed * fix locking behaviour * seek slider disabled on Microsoft VM * set User-Agent and add SVN info to About dialog * extensively tested on Windows XP and 2000 with Microsoft VM * extensively tested on Linux, Windows XP and 2000 with Sun VM 1.4.0_01, 1.4.2_12, 1.5.0_03, 1.5.0_06, 1.5.0_09 Bugs fixed since 0.2.1: * 390 : README not inline with code * 423 : cortado: playback of ogg audio * 63 : stops after a few frames on certain browser/jdk combinations * 149 : cortado 0.1.0 freeze because of javax.sound * 155 : implement pause/play in cortado, with javascript methods * 157 : Cortado is not doing any playback if the file has no audio while the applet is loaded with audio=true parameter * 317 : cortado should do typefinding on its input instead of relying on mime type from server * 384 : Cortado: Only play on click ­[in video-window] * 389 : Cortado needs option to make status bar always visible * 390 : README not inline with code * 470 : stop() method raise a java.security.AccessControlException when calling Changes since 0.2.0: * Documentation updates * Very preliminary Annodex support Bugs fixed since 0.2.0: * 390 : README not inline with code Changes since 0.1.2: * Seeking in on-demand files and streams * Deadlock fixes * Build now uses ant * Shutdown fixes * Autoplugging based on mimetype; makes local file playback work * Autodect audio backend from sun.audio or javax.sound Bugs fixed since 0.1.2: * 265 : NullPointerException * 142 : JPEG applet's internal buffering produces "lag" * 367 : cortado fails to build on ubuntu dapper Changes since 0.1.0: * multiple instances of cortado now work correctly * various playback and buffering fixes cortado-0.6.0/README100644 0 0 22127 11350725171 11205 0ustar 0 0 WHAT IT IS ---------- This is Cortado, a multimedia framework for Java written by Fluendo. It contains: - JST, a port of the GStreamer 0.10 design to Java - jcraft, a copy of the JCraft JOgg/Jorbis code - jheora, an implementation of Theora in Java - jkate, an implementation of a basic Kate decoder in Java - jtiger, a basic Kate renderer (simple text/images only for now) - codecs (currently only containing the Smoke codec, a variant on Jpeg) - JST plugins for: - HTTP source element - Ogg and Multipart demuxers - Theora, JPEG and Smoke video decoders - Vorbis and MuLaw audio decoders - Java 1.1 sun.audio API audio sink - Java 1.4 javax.sound.sampled API audio sink - Overlay element - Kate text decoder and overlay - Selector element - examples - applets This release has support for - seeking in on-demand files - the above-mentioned plugins - basic HTTP authentication - buffering FAQ --- For frequently asked questions check our website at http://theora.org/cortado/ If any questions should be added, let us know. BUGS ---- You can file bugs at Xiph's issue tracker: https://trac.xiph.org/newticket?component=Cortado Make sure to choose the "Cortado" component. BUILDING -------- The build uses ant exclusively now. Normally, running ant Should build everything, if your system is setup correctly. You can copy build.config.sample to build.config and tweak it to choose certain settings. Run ant -p to see all the possible targets. EXAMPLES -------- You need a Java Virtual Machine to run the example code. You also need to set the classpath to your build tree when running (output/build/debug or output/build/stripped) - Jikes does not have a VM - gij (the GNU Java VM) does not have a javax.sound.sampled implementation, so fails when playing audio, but can still play video-only files - Sun Java VM works for me: /usr/java/jre1.5.0_04/bin/java -cp output/build/debug com.fluendo.examples.Player http://stream.fluendo.com:8850 (with a JPackage java-1.5.0-sun package) /usr/lib/jvm/java-1.5.0-sun-1.5.0.05/jre/bin/java -cp output/build/debug com.fluendo.examples.Player http://stream.fluendo.com:8850 USAGE ----- Embed the applet in a web page with code like this: ---- ---- parameters: ----------- url: string the URL to load, must be a fully qualified URL. IMPORTANT: if the applet is not signed, the hostname of the url *is required* to be the same as the hostname of the link to the page with the applet tag. This is a Java security limitation. seekable: enum (auto|true|false) Whether or not you can seek in the file. For live streams, this should be false; for on-demand files, this can be true. In automatic mode, the stream becomes seekable when the content length is discovered. Defaults to auto live enum (auto|true|false) Whether or not this file is a live stream. For live streams, this should be true, which will disable the PAUSE button. For on-demand files, this can be false. In automatic mode, the stream becomes non-live when the content length is discovered. Defaults to auto duration: int Length of clip in seconds. Needed when seekable is true, to allow the seek bar to work. keepAspect: boolean Try to keep the natural aspect of the video when resizing the applet window. true or false. Defaults to true ignoreAspect: boolean Ignore the aspect ratio as signalled by the video, always assume square pixels. true or false. Defaults to false video: boolean Use video. When not using video, this property will not create resources to play a video stream. true or false. Defaults to true audio: boolean Use audio. When not using audio, this property will not create resources to play an audio stream. true or false. Defaults to true kateIndex: int Use text from the given Kate stream (indexed from zero). The first Kate stream found will have index 0, the second will have index 1, etc. Selecting a Kate stream by index takes priority over selecting by language and/or category. At most one Kate stream may be enabled at a time. Defaults to -1 (none) kateLanguage: string Use text from the Kate stream with the given language (ISO 639-1 tag). Selecting a Kate stream by index takes priority over selecting by language and/or category. At most one Kate stream may be enabled at a time. Defaults to null (none) kateCategory: string Use text from the Kate stream with the given category. Selecting a Kate stream by index takes priority over selecting by language and/or category. At most one Kate stream may be enabled at a time. Defaults to null (none) statusHeight: int The height of the status area (default 12) autoPlay: boolean Automatically start playback (default true) showStatus: enum (auto|show|hide) Controls how to make the status area visible. auto will show the status area when hovered over with the mouse. hide will only show the status area on error. show will always show the status area. (default auto) showSpeaker: boolean Show a speaker icon when audio is available (default true) showSubtitles: boolean Show a subtitles icon when subtitles are available (default true) hideTimeout: int Timeout in seconds to hide the status area when showStatus is auto. This timeout is to make sure that the status area is visible for the first timeout seconds of playback so that the user can see that there is a clickable status area too. (default 0) bufferSize: int The size of the network buffer, in KB. A good value is max Kbps of the stream * 33 Defaults to 200 bufferLow: int Percentage of low watermark for buffer. Below this, the applet will stop playing and rebuffer until the high watermark is reached. Defaults to 10 bufferHigh: int Percentage of high watermark for buffer. At startup or when rebuffering, the applet will not play until this percentage of buffer fill status is reached. Defaults to 70 userId: string user id for basic authentication. password: string password for basic authentication. debug: int debug level, 0 - 4. Defaults to 3. Output goes to the Java console. Using javascript ---------------- The applet parameters can be changed from javascript by calling the setParam(key, value) on the applet. After setting the new parameters in the applet it needs to be restarted with the restart() method for the changes to take effect. Likewise, applet parameters may be queried using getParam(key, default). The following piece of HTML demonstrates switching URLs with an without sound using javascript: ----

---- The applet can be controlled with the following javascript methods: doPlay(): Start playback doPause(): Pause playback doStop(): Stop playback doSeek(double pos); seek to a new position, must be between 0.0 and 1.0. getPlayPosition(): returns current position in seconds cortado-0.6.0/RELEASE100644 0 0 1272 11350736751 11314 0ustar 0 0 == Cortado applet == Release notes for Cortado 0.6.0, "Increasing increase" === Features of this release === Please refer to the NEWS file for an overview of changes. === Download === You can find source releases and built applets of cortado in the download directory: http://downloads.xiph.org/releases/cortado/ === Cortado Homepage === More details can be found on the project's website: http://theora.org/cortado/ === Support and Bugs === We use an issue tracker for bug reports and feature requests: https://trac.xiph.org/ === Developers === All code is in GIT and can be checked out from there. It is hosted on http://git.xiph.org/?p=cortado.git   cortado-0.6.0/TODO100644 0 0 1761 11271647733 11007 0ustar 0 0 TODO for cortado - recover from discont in oggdemux - implement Query duration/position, not sure how to do that since we only have the byte position. possibly put duration as a param or maybe do a single seek for the last page to get the last granule position. We need position/duration in time to implement current position in the GUI since using the byte position would result in values way past the actual playback position because of buffering. - clean up some issues with pause/play stuttering. - disable sound option - possibly use java2 image functions? - network speed? - pop up an error dialog for java.security.AccessControlException when doing at java.net.URLConnection.getContentType(Unknown Source) at com.fluendo.player.Cortado.start(Cortado.java:432) at sun.applet.AppletPanel.run(Unknown Source) to tell the user his stream and his applet need to be on the same server - generate cortado.spec - generate Dist.java during build only when it is not already there wim cortado-0.6.0/build.properties100644 0 0 1207 11350743065 13520 0ustar 0 0 # properties in this file can be customized in build.config # please do not customize this file # product information product.name cortado # Product version or GIT for git snapshot product.version 0.6.0 # which compiler to use; "modern" or "jikes" currently work # used by all javac tasks by default build.compiler extJavac # choose between debug and stripped builds build.type debug # what things to debug in the debug build build.debuglevel lines,vars,source # choose additional compiler flags # FIXME: these can be used to set debug flags for jikes with ant < 1.6.5 build.debug.flags build.stripped.flags cortado-0.6.0/build.xml100644 0 0 61075 11350725171 12153 0ustar 0 0 Cortado ANT build file package com.fluendo.player; class Configure { public String buildInfo = "Built on ${DATE} GMT (version ${real_version}) in ${build.type} mode."; public String buildDate = "${DATE} GMT"; public String buildVersion = "${real_version}"; public String buildType = "${build.type}"; public String revision = "${REVISION}"; public String branch = "${BRANCH}"; public Configure() { } } Built on ${DATE} (version ${real_version}) in ${build.type} mode. ${OUTPUT} ${SPECOUTPUT} Generating ${out.buildtyped}/includes com/fluendo/player/* com/fluendo/utils/* com/fluendo/jst/* com/fluendo/plugin/AudioSink* com/fluendo/plugin/VideoSink** com/fluendo/plugin/FakeSink* com/fluendo/plugin/Overlay* com/fluendo/plugin/HTTPSrc* com/fluendo/plugin/Queue* com/fluendo/plugin/Selector* Including JPEG com/fluendo/plugin/JPEG* Including Mulaw com/fluendo/plugin/Mulaw* Including Multipart com/fluendo/plugin/Multipart* Including Ogg com/jcraft/jogg/* com/fluendo/plugin/Ogg* Including Smoke com/fluendo/codecs/Smoke* com/fluendo/plugin/Smoke* Including Theora com/fluendo/jheora/* com/fluendo/plugin/Theora* Including Vorbis com/jcraft/jorbis/* com/fluendo/plugin/Vorbis* Including Kate com/fluendo/jkate/* com/fluendo/jtiger/* com/fluendo/plugin/Kate* ${test} cortado-0.6.0/cortado.doap100644 0 0 12363 11270111317 12616 0ustar 0 0 Cortado cortado 2004-11-19 Cortado is a multimedia framework for Java written by Fluendo. This is Cortado, a multimedia framework for Java written by Fluendo. It contains: - JST, a port of the GStreamer 0.10 design to Java - jcraft, a copy of the JCraft JOgg/Jorbis code - jheora, an implementation of Theora in Java - codecs (currently only containing the Smoke codec, a variant on Jpeg) - JST plugins for: - HTTP source element - Ogg and Multipart demuxers - Theora, JPEG and Smoke video decoders - Vorbis and MuLaw audio decoders - Java 1.1 sun.audio API audio sink - Java 1.4 javax.sound.sampled API audio sink - examples - applets Java git://git.xiph.org/cortado cortado Wim Taymans 0.1.0 0.1 Merry Christmas 2004-12-24 0.1.2 0.1 Semicolon 2005-04-22 0.2.0 0.2 Broken Record 2006-05-19 0.2.1 0.2 Flapoorke 2006-09-14 0.2.2 0.2 Really Tested Verily Exceptionally 2006-10-26 cortado-0.6.0/cortado.spec100644 0 0 2463 11350743266 12622 0ustar 0 0 Name: cortado Version: 0.6.0 Release: 1 Summary: Cortado - a Java media framework Group: Applications/Multimedia License: GPL/LGPL/BSD URL: http://www.theora.org/cortado/ Source: http://downloads.xiph.org/releases/cortado/%{name}-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root BuildRequires: ant %description Cortado is a Java media framework based on GStreamer's design. %prep %setup -q %build ant %install rm -rf $RPM_BUILD_ROOT ant -Dprefix=$RPM_BUILD_ROOT%{_prefix} install_class ant -Dprefix=$RPM_BUILD_ROOT%{_prefix} -Dtype=stripped install_applet ant -Dprefix=$RPM_BUILD_ROOT%{_prefix} -Dtype=debug install_applet # make some symlinks so that we can have a version-independent cortado for type in ov ovt mmjs do ln -sf %{_datadir}/cortado/cortado-$type-debug-%{version}.jar \ $RPM_BUILD_ROOT%{_datadir}/cortado/cortado-$type.jar done %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root,-) %doc LICENSE.* HACKING README NEWS RELEASE TODO cortado.doap %{_libdir}/cortado %{_datadir}/cortado %changelog * Thu Nov 5 2009 Ralph Giles - Update the URLs; since 0.5.0 the project has been hosted at xiph.org. * Thu Oct 26 2006 Thomas Vander Stichele - add doap file cortado-0.6.0/cortado.spec.in100644 0 0 2477 11275251770 13234 0ustar 0 0 Name: cortado Version: @VERSION@ Release: @RELEASE@ Summary: Cortado - a Java media framework Group: Applications/Multimedia License: GPL/LGPL/BSD URL: http://www.theora.org/cortado/ Source: http://downloads.xiph.org/releases/cortado/%{name}-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root BuildRequires: ant %description Cortado is a Java media framework based on GStreamer's design. %prep %setup -q %build ant %install rm -rf $RPM_BUILD_ROOT ant -Dprefix=$RPM_BUILD_ROOT%{_prefix} install_class ant -Dprefix=$RPM_BUILD_ROOT%{_prefix} -Dtype=stripped install_applet ant -Dprefix=$RPM_BUILD_ROOT%{_prefix} -Dtype=debug install_applet # make some symlinks so that we can have a version-independent cortado for type in ov ovt mmjs do ln -sf %{_datadir}/cortado/cortado-$type-debug-%{version}.jar \ $RPM_BUILD_ROOT%{_datadir}/cortado/cortado-$type.jar done %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root,-) %doc LICENSE.* HACKING README NEWS RELEASE TODO cortado.doap %{_libdir}/cortado %{_datadir}/cortado %changelog * Thu Nov 5 2009 Ralph Giles - Update the URLs; since 0.5.0 the project has been hosted at xiph.org. * Thu Oct 26 2006 Thomas Vander Stichele - add doap file cortado-0.6.0/src/com/fluendo/codecs/SmokeCodec.java100644 0 0 11702 11270111317 17432 0ustar 0 0 /* Smoke Codec * Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.codecs; import java.awt.*; public class SmokeCodec { private static final int IDX_TYPE = 0; private static final int IDX_WIDTH = 1; private static final int IDX_HEIGHT = 3; private static final int IDX_FPS_NUM = 5; private static final int IDX_FPS_DENOM = 9; private static final int IDX_FLAGS = 13; private static final int IDX_NUM_BLOCKS = 14; private static final int IDX_SIZE = 16; private static final int IDX_BLOCKS = 18; private static final int OFFS_PICT = 18; private Image reference; private MediaTracker mt; private Component component; private Toolkit toolkit; public static final int KEYFRAME = (1<<0); public int type; public int width, height; public int fps_num, fps_denom; public int flags; public int size; public int blocks; public SmokeCodec(Component comp, MediaTracker tracker) { component = comp; toolkit = comp.getToolkit(); mt = tracker; } public int parseHeader (byte[] in, int offset, int length) { short b1, b2, b3, b4; type = in[IDX_TYPE+offset]; b1 = in[IDX_WIDTH+offset]; if (b1<0) b1 += 256; b2 = in[IDX_WIDTH+1+offset]; if (b2<0) b2 += 256; width = (b1 << 8) | b2; b1 = in[IDX_HEIGHT+offset]; if (b1<0) b1 += 256; b2 = in[IDX_HEIGHT+1+offset]; if (b2<0) b2 += 256; height = (b1 << 8) | b2; b1 = in[IDX_FPS_NUM+offset]; if (b1<0) b1 += 256; b2 = in[IDX_FPS_NUM+1+offset]; if (b2<0) b2 += 256; b3 = in[IDX_FPS_NUM+2+offset]; if (b3<0) b3 += 256; b4 = in[IDX_FPS_NUM+3+offset]; if (b4<0) b4 += 256; fps_num = (b1<<24) | (b2<<16) | (b3<<8) | b4; b1 = in[IDX_FPS_DENOM+offset]; if (b1<0) b1 += 256; b2 = in[IDX_FPS_DENOM+1+offset]; if (b2<0) b2 += 256; b3 = in[IDX_FPS_DENOM+2+offset]; if (b3<0) b3 += 256; b4 = in[IDX_FPS_DENOM+3+offset]; if (b4<0) b4 += 256; fps_denom = (b1<<24) | (b2<<16) | (b3<<8) | b4; flags = in[IDX_FLAGS+offset]; b1 = in[IDX_SIZE+offset]; if (b1<0) b1 += 256; b2 = in[IDX_SIZE+offset]; if (b2<0) b2 += 256; size = (b1 << 8) | b2; b1 = in[IDX_NUM_BLOCKS+offset]; if (b1<0) b1 += 256; b2 = in[IDX_NUM_BLOCKS+1+offset]; if (b2<0) b2 += 256; blocks = (b1 << 8) | b2; return 0; } public Image decode (byte[] in, int offset, int length) { int b1,b2; parseHeader(in, offset, length); boolean keyframe = ((flags & KEYFRAME) != 0); if (reference == null && !keyframe) { return null; } //System.out.println("blocks: "+blocks+" width "+width+" height "+height); int imgoff = blocks*2+OFFS_PICT; //System.out.println("decoding "+blocks+" "+imgoff+" "+(length-imgoff)+" "+keyframe); Image src = null; try { src = toolkit.createImage(in, imgoff+offset, length-imgoff); } catch (Exception e) {e.printStackTrace();} if (src == null) { System.out.println("failed"); return null; } try { mt.addImage(src, 0); mt.waitForID(0); mt.removeImage(src, 0); } catch (Exception e) {e.printStackTrace();} if (reference == null || keyframe) { reference = src; } else { if (blocks > 0 ) { int src_w = src.getWidth(null); int src_h = src.getHeight(null); int blockptr = 0; int pos, i, j, x, y; Graphics refgfx; offset += IDX_BLOCKS; Image newref = component.createImage(width, height); refgfx = newref.getGraphics(); refgfx.drawImage(reference, 0, 0, null); reference = newref; for (i=0; i= blocks) break; } } } } //System.out.println("decoded "+blocks+" "+imgoff+" "+(length-imgoff)+" "+keyframe+" "+reference); return reference; } } cortado-0.6.0/src/com/fluendo/examples/DCTTest.java100644 0 0 12330 11274361740 17257 0ustar 0 0 /* Copyright (C) <2009> Maik Merten * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.examples; import com.fluendo.jheora.Constants; import com.fluendo.jheora.iDCT; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; public class DCTTest { /* // create a lookup-table to translate into zig-zag private static int[] zigzag; static { zigzag = new int[64]; for (int i = 0; i < 64; ++i) { int idx = Constants.dequant_index[i]; zigzag[idx] = i; } } private static short[] zigzag(short[] input) { short[] result = new short[64]; for (int i = 0; i < 64; ++i) { result[zigzag[i]] = input[i]; } return result; } private static void fillArray(short[] array, String line) { String[] tokens = line.trim().split(" "); int i = tokens.length; int cnt = 0; while (--i >= 0 && cnt < 64) { int idx = (array.length - 1) - cnt; //System.out.println(idx + " " + tokens[i]); array[idx] = Short.parseShort(tokens[i]); cnt++; } } private static String pad(short s) { String result = s + ""; while (result.length() < 4) { result = " " + result; } return result; } public static void main(String[] args) throws IOException { if (args.length != 1) { System.err.println("usage: DCTTest "); System.exit(1); } File input = new File(args[0]); BufferedReader br = new BufferedReader(new FileReader(input)); short[] quantizers = new short[64]; short[] quantized_coeffs = new short[64]; short[] coeffs = new short[64]; short[] result = new short[64]; short[] myresult = new short[64]; boolean b1 = false, b2 = false, b3 = false, b4 = false; iDCT dct = new iDCT(); int cnt = 0; String line = br.readLine(); while (line != null) { // empty lines indicate next block of test data if (line.trim().length() == 0) { b1 = b2 = b3 = b4 = false; } if (line.startsWith("QUANTIZER:")) { fillArray(quantizers, line); b1 = true; } else if (line.startsWith("QUANTIZED_COEFFS:")) { fillArray(quantized_coeffs, line); b2 = true; } else if (line.startsWith("DCT_COEFFICIENTS:")) { fillArray(coeffs, line); b3 = true; } else if (line.startsWith("DCT_RESULT:")) { fillArray(result, line); b4 = true; } // got a complete block of test data, so let's test if (b1 && b2 && b3 && b4) { // iDCT.java expects the coeffs to be zig-zagged! quantized_coeffs = zigzag(quantized_coeffs); quantizers = zigzag(quantizers); boolean just10 = true; for (int i = 10; i < 64; ++i) { if (quantized_coeffs[i] != 0) { just10 = false; break; } } if (just10) { dct.IDct10(quantized_coeffs, quantizers, myresult); } else { dct.IDctSlow(quantized_coeffs, quantizers, myresult); } boolean pass = true; for (int i = 0; i < 64; ++i) { if (result[i] != myresult[i]) { pass = false; break; } } System.out.println("test vector " + ++cnt + (pass ? " passed " : " didn't pass ") + " using " + (just10 ? " fast DCT " : " slow DCT.")); if (!pass) { System.out.print("reference: "); for (int i = 0; i < result.length; ++i) { System.out.print(" " + pad(result[i])); } System.out.println(); System.out.print("iDCT.java: "); for (int i = 0; i < myresult.length; ++i) { System.out.print(" " + pad(myresult[i])); } System.out.println(); System.out.println(); } } line = br.readLine(); } }*/ } cortado-0.6.0/src/com/fluendo/examples/DumpVideo.java100644 0 0 26624 11274362453 17716 0ustar 0 0 /* Copyright (C) <2009> Maik Merten * Copyright (C) <2004> Wim Taymans (TheoraDec.java parts) * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.examples; import com.fluendo.jheora.Comment; import com.fluendo.jheora.Info; import com.fluendo.jheora.State; import com.fluendo.jheora.YUVBuffer; import com.fluendo.utils.Debug; import com.fluendo.utils.MemUtils; import com.jcraft.jogg.Packet; import com.jcraft.jogg.Page; import com.jcraft.jogg.StreamState; import com.jcraft.jogg.SyncState; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; /** * This class borrows code from TheoraDec.java */ public class DumpVideo { public static final Integer OK = new Integer(0); public static final Integer ERROR = new Integer(-5); private static final byte[] signature = {-128, 0x74, 0x68, 0x65, 0x6f, 0x72, 0x61}; private class TheoraDecoder { private Info ti; private Comment tc; private State ts; private YUVBuffer yuv; private int packet; private boolean needKeyframe; public TheoraDecoder() { super(); ti = new Info(); tc = new Comment(); ts = new State(); yuv = new YUVBuffer(); } public int takeHeader(Packet op) { int ret; byte header; ret = ti.decodeHeader(tc, op); header = op.packet_base[op.packet]; if (header == -126) { ts.decodeInit(ti); } return ret; } public boolean isHeader(Packet op) { return (op.packet_base[op.packet] & 0x80) == 0x80; } public boolean isKeyFrame(Packet op) { return ts.isKeyframe(op); } public Object decode(Packet op) { Object result = OK; if (packet < 3) { //System.out.println ("decoding header"); if (takeHeader(op) < 0) { // error case; not a theora header Debug.log(Debug.ERROR, "does not contain Theora video data."); return ERROR; } if (packet == 2) { ts.decodeInit(ti); Debug.log(Debug.INFO, "theora dimension: " + ti.width + "x" + ti.height); if (ti.aspect_denominator == 0) { ti.aspect_numerator = 1; ti.aspect_denominator = 1; } Debug.log(Debug.INFO, "theora offset: " + ti.offset_x + "," + ti.offset_y); Debug.log(Debug.INFO, "theora frame: " + ti.frame_width + "," + ti.frame_height); Debug.log(Debug.INFO, "theora aspect: " + ti.aspect_numerator + "/" + ti.aspect_denominator); Debug.log(Debug.INFO, "theora framerate: " + ti.fps_numerator + "/" + ti.fps_denominator); } packet++; return OK; } else { if ((op.packet_base[op.packet] & 0x80) == 0x80) { Debug.log(Debug.INFO, "ignoring header"); return OK; } if (needKeyframe && ts.isKeyframe(op)) { needKeyframe = false; } if (!needKeyframe) { try { if (ts.decodePacketin(op) != 0) { Debug.log(Debug.ERROR, "Bad Theora packet. Most likely not fatal, hoping for better luck next packet."); } if (ts.decodeYUVout(yuv) != 0) { Debug.log(Debug.ERROR, "Error getting the picture."); return ERROR; } return yuv.getObject(ti.offset_x, ti.offset_y, ti.frame_width, ti.frame_height); } catch (Exception e) { e.printStackTrace(); result = ERROR; } } else { result = OK; } } packet++; return result; } } private class YUVWriter { private OutputStream os; private boolean wroteHeader = false; private byte[] ybytes; private byte[] uvbytes; private boolean raw; public YUVWriter(File outfile, boolean raw) { this.raw = raw; try { os = new FileOutputStream(outfile); } catch (FileNotFoundException ex) { ex.printStackTrace(); } } public void writeYUVFrame(Info ti, YUVBuffer yuv) { try { if (!raw) { if (!wroteHeader) { String headerstring = "YUV4MPEG2 W" + ti.width + " H" + ti.height + " F" + ti.fps_numerator + ":" + ti.fps_denominator + " Ip A" + ti.aspect_numerator + ":" + ti.aspect_denominator + "\n"; os.write(headerstring.getBytes()); wroteHeader = true; } os.write("FRAME\n".getBytes()); } if (ybytes == null || ybytes.length != yuv.y_width * yuv.y_height) { ybytes = new byte[yuv.y_width * yuv.y_height]; } int offset = 0; for (int i = 0; i < yuv.y_height; ++i) { int start = yuv.y_offset + (i * yuv.y_stride); for (int j = start; j < start + yuv.y_width; ++j) { ybytes[offset++] = (byte) yuv.data[j]; } } os.write(ybytes); if (uvbytes == null || uvbytes.length != yuv.uv_width * yuv.uv_height) { uvbytes = new byte[yuv.uv_width * yuv.uv_height]; } offset = 0; for (int i = 0; i < yuv.uv_height; ++i) { int start = yuv.u_offset + (i * yuv.uv_stride); for (int j = start; j < start + yuv.uv_width; ++j) { uvbytes[offset++] = (byte) yuv.data[j]; } } os.write(uvbytes); offset = 0; for (int i = 0; i < yuv.uv_height; ++i) { int start = yuv.v_offset + (i * yuv.uv_stride); for (int j = start; j < start + yuv.uv_width; ++j) { uvbytes[offset++] = (byte) yuv.data[j]; } } os.write(uvbytes); } catch (IOException ex) { ex.printStackTrace(); } } } public boolean isTheora(Packet op) { return typeFind(op.packet_base, op.packet, op.bytes) > 0; } public int typeFind(byte[] data, int offset, int length) { if (MemUtils.startsWith(data, offset, length, signature)) { return 10; } return -1; } public void dumpVideo(File videofile, List outfiles, boolean raw) throws IOException { InputStream is = new FileInputStream(videofile); SyncState oy = new SyncState(); Page og = new Page(); Packet op = new Packet(); byte[] buf = new byte[512]; Map streamstates = new HashMap(); Map theoradecoders = new HashMap(); Map yuvwriters = new HashMap(); Set hasdecoder = new HashSet(); int frames = 0; int read = is.read(buf); while (read > 0) { int offset = oy.buffer(read); java.lang.System.arraycopy(buf, 0, oy.data, offset, read); oy.wrote(read); while (oy.pageout(og) == 1) { Integer serialno = new Integer(og.serialno()); StreamState state = (StreamState) streamstates.get(serialno); if (state == null) { state = new StreamState(); state.init(serialno.intValue()); streamstates.put(serialno, state); Debug.info("created StreamState for stream no. " + og.serialno()); } state.pagein(og); while (state.packetout(op) == 1) { if (!(hasdecoder.contains(serialno)) && isTheora(op)) { TheoraDecoder theoradec = (TheoraDecoder) theoradecoders.get(serialno); if (theoradec == null) { theoradec = new TheoraDecoder(); theoradecoders.put(serialno, theoradec); hasdecoder.add(serialno); } Debug.info("is Theora: " + serialno); } TheoraDecoder theoradec = (TheoraDecoder) theoradecoders.get(serialno); if (theoradec != null) { Object result = theoradec.decode(op); if (result instanceof YUVBuffer) { Debug.info("got frame " + ++frames); YUVWriter yuvwriter = (YUVWriter) yuvwriters.get(serialno); if (yuvwriter == null && !outfiles.isEmpty()) { yuvwriter = new YUVWriter((File) outfiles.get(0), raw); yuvwriters.put(serialno, yuvwriter); outfiles.remove(0); } if (yuvwriter != null) { YUVBuffer yuvbuf = (YUVBuffer) result; yuvwriter.writeYUVFrame(theoradec.ti, yuvbuf); } } } } } read = is.read(buf); } } public static void main(String[] args) throws IOException { if (args.length < 2) { System.err.println("usage: DumpVideo ... [--raw>]"); System.exit(1); } boolean raw = false; File infile = new File(args[0]); List outfiles = new LinkedList(); for (int i = 1; i < args.length; ++i) { if(args[i].equals("--raw")) { raw = true; break; } outfiles.add(new File(args[i])); } DumpVideo dv = new DumpVideo(); dv.dumpVideo(infile, outfiles, raw); } } cortado-0.6.0/src/com/fluendo/examples/OggPerf.java100644 0 0 10520 11270111317 17322 0ustar 0 0 /* Cortado - a video player java applet * Copyright (C) 2004 Fluendo S.L. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. */ package com.fluendo.examples; import java.io.*; import java.util.*; import com.jcraft.jogg.*; public class OggPerf { private static final int BUFFSIZE = 8192; private InputStream inputStream; private SyncState oy; private Vector streams; private boolean stopping; class OggStream { public int serialno; public StreamState os; public boolean bos; public OggStream (int serial) { serialno = serial; os = new StreamState(); os.init(serial); os.reset(); bos = true; } } public OggPerf (InputStream is) { inputStream = is; oy = new SyncState(); streams = new Vector(); stopping = false; } public static void main(String[] args) { try { int run = 10; long start = System.currentTimeMillis(); while (run-- > 0) { OggPerf perf = new OggPerf(new FileInputStream(args[0])); perf.start(); } long end = System.currentTimeMillis(); System.out.println("ellapsed: "+(end-start)); } catch (Exception e) { e.printStackTrace(); } } public void start() { int res; Page og; Packet op; System.out.println("started ogg reader"); og = new Page(); op = new Packet(); try { while (!stopping) { int index = oy.buffer(BUFFSIZE); //System.out.println("reading "+index+" "+BUFFSIZE); int read = inputStream.read(oy.data, index, BUFFSIZE); //System.out.println("read "+read); if (read < 0) break; oy.wrote(read); while (!stopping) { res = oy.pageout(og); //System.out.println("pageout "+res); if (res == 0) break; // need more data if(res == -1) { // missing or corrupt data at this page position // no reason to complain; already complained above } else { int serial = og.serialno(); OggStream stream = null; for (int i=0; i 0) { OggTheoraPerf perf = new OggTheoraPerf(new FileInputStream(args[0])); perf.start(); } long end = System.currentTimeMillis(); System.out.println("ellapsed: "+(end-start)); } catch (Exception e) { e.printStackTrace(); } } public void start() { int res; Page og; Packet op; System.out.println("started ogg reader"); og = new Page(); op = new Packet(); try { while (!stopping) { int index = oy.buffer(BUFFSIZE); //System.out.println("reading "+index+" "+BUFFSIZE); int read = inputStream.read(oy.data, index, BUFFSIZE); //System.out.println("read "+read); if (read < 0) break; oy.wrote(read); while (!stopping) { res = oy.pageout(og); //System.out.println("pageout "+res); if (res == 0) break; // need more data if(res == -1) { // missing or corrupt data at this page position // no reason to complain; already complained above } else { int serial = og.serialno(); OggStream stream = null; for (int i=0; i"); return; } p = new Player(args[0]); synchronized (p) { try { p.wait (); } catch (InterruptedException ie) {} } } } cortado-0.6.0/src/com/fluendo/jheora/BlockMapping.java100644 0 0 6774 11336021765 20003 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; public final class BlockMapping { private int[][][] blockMap; private static final int[] mbOrderMap = { 0, 2, 3, 1 }; private static final int[][] blockOrderMap1 = { { 0, 1, 3, 2 }, { 0, 2, 3, 1 }, { 0, 2, 3, 1 }, { 3, 2, 0, 1 } }; public final int quadMapToIndex1 (int sb, int mb, int b) { return blockMap[sb][mbOrderMap[mb]][blockOrderMap1[mb][b]]; } public final int quadMapToMBTopLeft (int sb, int mb) { return blockMap[sb][mbOrderMap[mb]][0]; } private void CreateMapping (int firstSB, int firstFrag, int hFrags, int vFrags) { int i = 0, j = 0; int xpos; int ypos; int mb, B; int sb=firstSB; int fragIndex=firstFrag; /* Set Super-Block dimensions */ int sBRows = (vFrags>>2) + ((vFrags & 0x3) != 0 ? 1 : 0 ); int sBCols = (hFrags>>2) + ((hFrags & 0x3) != 0 ? 1 : 0 ); /* Map each Super-Block */ for (int sBRow=0; sBRow> 1); B = ((i & 1) << 1) + (j & 1); /* Set mapping and move to next fragment */ blockMap[sb][mb][B] = fragIndex++; } /* Move to first fragment in next row in Super-Block */ fragIndex += hFrags-j; } /* Move on to next Super-Block */ sb++; fragIndex -= i*hFrags-j; } /* Move to first Super-Block in next row */ fragIndex += 3*hFrags; } } public BlockMapping (int ySuperBlocks, int uvSuperBlocks, int hFrags, int vFrags, int shiftx, int shifty) { blockMap = new int[ySuperBlocks + uvSuperBlocks * 2][4][4]; for (int i=0; i>shiftx, vFrags>>shifty ); CreateMapping (ySuperBlocks + uvSuperBlocks, hFrags*vFrags + (hFrags>>shiftx)*(vFrags>>shifty), hFrags>>shiftx, vFrags>>shifty ); } } cortado-0.6.0/src/com/fluendo/jheora/CodingMode.java100644 0 0 4516 11270111317 17423 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; public class CodingMode { private int value; public static final CodingMode CODE_INTER_NO_MV = new CodingMode(0x0); /* INTER prediction, (0,0) motion vector implied. */ public static final CodingMode CODE_INTRA = new CodingMode(0x1); /* INTRA i.e. no prediction. */ public static final CodingMode CODE_INTER_PLUS_MV = new CodingMode(0x2); /* INTER prediction, non zero motion vector. */ public static final CodingMode CODE_INTER_LAST_MV = new CodingMode(0x3); /* Use Last Motion vector */ public static final CodingMode CODE_INTER_PRIOR_LAST = new CodingMode(0x4); /* Prior last motion vector */ public static final CodingMode CODE_USING_GOLDEN = new CodingMode(0x5); /* 'Golden frame' prediction (no MV). */ public static final CodingMode CODE_GOLDEN_MV = new CodingMode(0x6); /* 'Golden frame' prediction plus MV. */ public static final CodingMode CODE_INTER_FOURMV = new CodingMode(0x7); /* Inter prediction 4MV per macro block. */ public static final CodingMode[] MODES = { CODE_INTER_NO_MV, CODE_INTRA, CODE_INTER_PLUS_MV, CODE_INTER_LAST_MV, CODE_INTER_PRIOR_LAST, CODE_USING_GOLDEN, CODE_GOLDEN_MV, CODE_INTER_FOURMV }; private CodingMode(int i) { value=i; } public int getValue() { return value; } } cortado-0.6.0/src/com/fluendo/jheora/Colorspace.java100644 0 0 2515 11270111317 17502 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; public class Colorspace { public static final Colorspace UNSPECIFIED = new Colorspace (); public static final Colorspace ITU_REC_470M = new Colorspace (); public static final Colorspace ITU_REC_470BG = new Colorspace (); public static final Colorspace[] spaces = { UNSPECIFIED, ITU_REC_470M, ITU_REC_470BG }; private Colorspace() { } } cortado-0.6.0/src/com/fluendo/jheora/Comment.java100644 0 0 2160 11270111317 17006 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; public class Comment { String[] user_comments; String vendor; public void clear() { user_comments = null; vendor = null; } } cortado-0.6.0/src/com/fluendo/jheora/Constants.java100644 0 0 4270 11270111317 17364 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; public class Constants { public static final int CURRENT_ENCODE_VERSION = 1; /* Baseline dct height and width. */ public static final int BLOCK_HEIGHT_WIDTH = 8; public static final int HFRAGPIXELS = 8; public static final int VFRAGPIXELS = 8; /* Baseline dct block size */ public static final int BLOCK_SIZE = (BLOCK_HEIGHT_WIDTH * BLOCK_HEIGHT_WIDTH); /* Border is for unrestricted mv's */ public static final int UMV_BORDER = 16; public static final int STRIDE_EXTRA = (UMV_BORDER * 2); public static final int Q_TABLE_SIZE = 64; public static final int BASE_FRAME = 0; public static final int NORMAL_FRAME = 1; public static final int MAX_MODES = 8; public static final int MODE_BITS = 3; public static final int MODE_METHODS = 8; public static final int MODE_METHOD_BITS = 3; public static final int[] dequant_index = { 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 }; } cortado-0.6.0/src/com/fluendo/jheora/Coordinate.java100644 0 0 2211 11270111317 17470 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; public class Coordinate { public int x, y; public Coordinate() { x=0; y=0; } public Coordinate(int x, int y) { this.x = x; this.y = y; } } cortado-0.6.0/src/com/fluendo/jheora/DCTDecode.java100644 0 0 74076 11336021765 17173 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; import com.fluendo.utils.*; public class DCTDecode { private static final int PUR = 8; private static final int PU = 4; private static final int PUL = 2; private static final int PL = 1; private short[] dequant_matrix = new short[64]; private static final int[] ModeUsesMC = { 0, 0, 1, 1, 1, 0, 1, 1 }; /* predictor multiplier up-left, up, up-right,left, shift Entries are packed in the order L, UL, U, UR, with missing entries moved to the end (before the shift parameters). */ private static final short[][] pc = { {0,0,0,0,0,0}, {1,0,0,0,0,0}, /* PL */ {1,0,0,0,0,0}, /* PUL */ {1,0,0,0,0,0}, /* PUL|PL */ {1,0,0,0,0,0}, /* PU */ {1,1,0,0,1,1}, /* PU|PL */ {0,1,0,0,0,0}, /* PU|PUL */ {29,-26,29,0,5,31}, /* PU|PUL|PL */ {1,0,0,0,0,0}, /* PUR */ {75,53,0,0,7,127}, /* PUR|PL */ {1,1,0,0,1,1}, /* PUR|PUL */ {75,0,53,0,7,127}, /* PUR|PUL|PL */ {1,0,0,0,0,0}, /* PUR|PU */ {75,0,53,0,7,127}, /* PUR|PU|PL */ {3,10,3,0,4,15}, /* PUR|PU|PUL */ {29,-26,29,0,5,31} /* PUR|PU|PUL|PL */ }; /* boundary case bit masks. */ private static final int[] bc_mask = { /* normal case no boundary condition */ PUR|PU|PUL|PL, /* left column */ PUR|PU, /* top row */ PL, /* top row, left column */ 0, /* right column */ PU|PUL|PL, /* right and left column */ PU, /* top row, right column */ PL, /* top row, right and left column */ 0 }; private static final short[] Mode2Frame = { 1, /* CODE_INTER_NO_MV 0 => Encoded diff from same MB last frame */ 0, /* CODE_INTRA 1 => DCT Encoded Block */ 1, /* CODE_INTER_PLUS_MV 2 => Encoded diff from included MV MB last frame */ 1, /* CODE_INTER_LAST_MV 3 => Encoded diff from MRU MV MB last frame */ 1, /* CODE_INTER_PRIOR_MV 4 => Encoded diff from included 4 separate MV blocks */ 2, /* CODE_USING_GOLDEN 5 => Encoded diff from same MB golden frame */ 2, /* CODE_GOLDEN_MV 6 => Encoded diff from included MV MB golden frame */ 1 /* CODE_INTER_FOUR_MV 7 => Encoded diff from included 4 separate MV blocks */ }; private short[] ReconDataBuffer = new short[64]; /* value left value up-left, value up, value up-right, missing values skipped. */ private int[] v = new int[4]; /* fragment number left, up-left, up, up-right */ private int[] fn = new int[4]; private short[] Last = new short[3]; private iDCT idct = new iDCT(); private void ExpandKFBlock ( Playback pbi, int FragmentNumber ){ int ReconPixelsPerLine; int ReconPixelIndex; short[] dequant_coeffs; /* determine which quantizer was specified for this block */ int qi = pbi.FragQs[FragmentNumber]; /* Select the appropriate inverse Q matrix and line stride */ if ( FragmentNumber<(int)pbi.YPlaneFragments ){ ReconPixelsPerLine = pbi.YStride; // intra Y dequant_coeffs = pbi.info.dequant_tables[0][0][pbi.frameQIS[qi]]; dequant_matrix[0] = pbi.info.dequant_tables[0][0][pbi.frameQIS[0]][0]; }else if(FragmentNumber < pbi.YPlaneFragments + pbi.UVPlaneFragments) { ReconPixelsPerLine = pbi.UVStride; // intra U dequant_coeffs = pbi.info.dequant_tables[0][1][pbi.frameQIS[qi]]; dequant_matrix[0] = pbi.info.dequant_tables[0][1][pbi.frameQIS[0]][0]; } else { ReconPixelsPerLine = pbi.UVStride; // intra V dequant_coeffs = pbi.info.dequant_tables[0][2][pbi.frameQIS[qi]]; dequant_matrix[0] = pbi.info.dequant_tables[0][2][pbi.frameQIS[0]][0]; } // create copy with DC coefficient of primary frame qi System.arraycopy(dequant_coeffs, 1, dequant_matrix, 1, 63); /* Set up pointer into the quantisation buffer. */ short[] quantized_list = pbi.QFragData[FragmentNumber]; /* Invert quantisation and DCT to get pixel data. */ switch(pbi.FragCoefEOB[FragmentNumber]){ case 0:case 1: idct.IDct1(quantized_list, dequant_matrix, ReconDataBuffer ); break; case 2: case 3:case 4:case 5:case 6:case 7:case 8: case 9:case 10: idct.IDct10(quantized_list, dequant_matrix, ReconDataBuffer ); break; default: idct.IDctSlow(quantized_list, dequant_matrix, ReconDataBuffer ); } /* for (int i=0; i<64; i++) { System.out.print(ReconDataBuffer[i]+" "); } System.out.println(); */ /* Convert fragment number to a pixel offset in a reconstruction buffer. */ ReconPixelIndex = pbi.recon_pixel_index_table[FragmentNumber]; /* Get the pixel index for the first pixel in the fragment. */ Recon.ReconIntra (pbi.ThisFrameRecon, ReconPixelIndex, ReconDataBuffer, ReconPixelsPerLine); } private void ExpandBlock ( Playback pbi, int FragmentNumber ){ short[] LastFrameRecPtr; /* Pointer into previous frame reconstruction. */ int ReconPixelsPerLine; /* Pixels per line */ int ReconPixelIndex; /* Offset for block into a reconstruction buffer */ int ReconPtr2Offset; /* Offset for second reconstruction in half pixel MC */ int MVOffset; /* Baseline motion vector offset */ int MvShiftX ; /* Shift to correct to 1/2 or 1/4 pixel */ int MvShiftY ; /* Shift to correct to 1/2 or 1/4 pixel */ int MvModMaskX; /* Mask to determine whether 1/2 pixel is used */ int MvModMaskY; short[] dequant_coeffs; CodingMode codingMode; /* determine which quantizer was specified for this block */ int qi = pbi.FragQs[FragmentNumber]; /* Get coding mode for this block */ if (pbi.getFrameType() == Constants.BASE_FRAME ){ codingMode = CodingMode.CODE_INTRA; }else{ /* Get Motion vector and mode for this block. */ codingMode = pbi.FragCodingMethod[FragmentNumber]; } /* Select the appropriate inverse Q matrix and line stride */ if ( FragmentNumber<(int)pbi.YPlaneFragments ) { ReconPixelsPerLine = pbi.YStride; MvShiftX = MvShiftY = 1; MvModMaskX = MvModMaskY = 0x00000001; /* Select appropriate dequantiser matrix. */ if ( codingMode == CodingMode.CODE_INTRA ) { // intra Y dequant_coeffs = pbi.info.dequant_tables[0][0][pbi.frameQIS[qi]]; dequant_matrix[0] = pbi.info.dequant_tables[0][0][pbi.frameQIS[0]][0]; } else { // inter Y dequant_coeffs = pbi.info.dequant_tables[1][0][pbi.frameQIS[qi]]; dequant_matrix[0] = pbi.info.dequant_tables[1][0][pbi.frameQIS[0]][0]; } }else{ ReconPixelsPerLine = pbi.UVStride; MvShiftX = pbi.UVShiftX + 1; MvShiftY = pbi.UVShiftY + 1; MvModMaskX = MvModMaskY = 0x00000003; if (MvShiftX == 1) MvModMaskX = 0x00000001; if (MvShiftY == 1) MvModMaskY = 0x00000001; /* Select appropriate dequantiser matrix. */ if(FragmentNumber < pbi.YPlaneFragments + pbi.UVPlaneFragments) { if ( codingMode == CodingMode.CODE_INTRA ) { // intra U dequant_coeffs = pbi.info.dequant_tables[0][1][pbi.frameQIS[qi]]; dequant_matrix[0] = pbi.info.dequant_tables[0][1][pbi.frameQIS[0]][0]; } else { // inter U dequant_coeffs = pbi.info.dequant_tables[1][1][pbi.frameQIS[qi]]; dequant_matrix[0] = pbi.info.dequant_tables[1][1][pbi.frameQIS[0]][0]; } } else { if ( codingMode == CodingMode.CODE_INTRA ) { // intra V dequant_coeffs = pbi.info.dequant_tables[0][2][pbi.frameQIS[qi]]; dequant_matrix[0] = pbi.info.dequant_tables[0][2][pbi.frameQIS[0]][0]; } else { // inter V dequant_coeffs = pbi.info.dequant_tables[1][2][pbi.frameQIS[qi]]; dequant_matrix[0] = pbi.info.dequant_tables[1][2][pbi.frameQIS[0]][0]; } } } // create copy with DC coefficient of primary frame qi System.arraycopy(dequant_coeffs, 1, dequant_matrix, 1, 63); /* Set up pointer into the quantisation buffer. */ short[] quantized_list = pbi.QFragData[FragmentNumber]; /* Invert quantisation and DCT to get pixel data. */ switch(pbi.FragCoefEOB[FragmentNumber]){ case 0:case 1: idct.IDct1(quantized_list, dequant_matrix, ReconDataBuffer ); break; case 2: case 3:case 4:case 5:case 6:case 7:case 8: case 9:case 10: idct.IDct10(quantized_list, dequant_matrix, ReconDataBuffer ); break; default: idct.IDctSlow(quantized_list, dequant_matrix, ReconDataBuffer ); } /* for (int i=0; i<64; i++) { System.out.print(ReconDataBuffer[i]+" "); } System.out.println(); */ /* Convert fragment number to a pixel offset in a reconstruction buffer. */ ReconPixelIndex = pbi.recon_pixel_index_table[FragmentNumber]; /* Action depends on decode mode. */ if ( codingMode == CodingMode.CODE_INTER_NO_MV ){ /* Inter with no motion vector */ /* Reconstruct the pixel data using the last frame reconstruction and change data when the motion vector is (0,0), the recon is based on the lastframe without loop filtering---- for testing */ Recon.ReconInter(pbi.ThisFrameRecon, ReconPixelIndex, pbi.LastFrameRecon, ReconPixelIndex, ReconDataBuffer, ReconPixelsPerLine ); }else if (ModeUsesMC[codingMode.getValue()] != 0) { /* The mode uses a motion vector. */ /* Get vector from list */ int dir; /* Work out the base motion vector offset and the 1/2 pixel offset if any. For the U and V planes the MV specifies 1/4 pixel accuracy. This is adjusted to 1/2 pixel as follows ( 0.0, 1/4->1/2, 1/2->1/2, 3/4->1/2 ). */ ReconPtr2Offset = 0; MVOffset = 0; dir = pbi.FragMVect[FragmentNumber].x; if (dir > 0) { MVOffset = dir >> MvShiftX; if ((dir & MvModMaskX) != 0 ) ReconPtr2Offset = 1; } else if (dir < 0) { MVOffset = -((-dir) >> MvShiftX); if (((-dir) & MvModMaskX) != 0 ) ReconPtr2Offset = -1; } dir = pbi.FragMVect[FragmentNumber].y; if ( dir > 0 ){ MVOffset += (dir >> MvShiftY) * ReconPixelsPerLine; if ((dir & MvModMaskY) != 0 ) ReconPtr2Offset += ReconPixelsPerLine; } else if (dir < 0 ){ MVOffset -= ((-dir) >> MvShiftY) * ReconPixelsPerLine; if (((-dir) & MvModMaskY) != 0 ) ReconPtr2Offset -= ReconPixelsPerLine; } int LastFrameRecOffset = ReconPixelIndex + MVOffset; /* Set up the first of the two reconstruction buffer pointers. */ if ( codingMode==CodingMode.CODE_GOLDEN_MV ) { LastFrameRecPtr = pbi.GoldenFrame; }else{ LastFrameRecPtr = pbi.LastFrameRecon; } /* System.out.println(pbi.FragMVect[FragmentNumber].x+" "+ pbi.FragMVect[FragmentNumber].y+" "+ ReconPixelIndex+" "+LastFrameRecOffset+ " "+ ReconPtr2Offset); */ /* Select the appropriate reconstruction function */ if (ReconPtr2Offset == 0 ) { /* Reconstruct the pixel dats from the reference frame and change data (no half pixel in this case as the two references were the same. */ Recon.ReconInter(pbi.ThisFrameRecon, ReconPixelIndex, LastFrameRecPtr, LastFrameRecOffset, ReconDataBuffer, ReconPixelsPerLine ); }else{ /* Fractional pixel reconstruction. */ /* Note that we only use two pixels per reconstruction even for the diagonal. */ Recon.ReconInterHalfPixel2(pbi.ThisFrameRecon, ReconPixelIndex, LastFrameRecPtr, LastFrameRecOffset, LastFrameRecPtr, LastFrameRecOffset+ReconPtr2Offset, ReconDataBuffer, ReconPixelsPerLine ); } } else if ( codingMode == CodingMode.CODE_USING_GOLDEN ){ /* Golden frame with motion vector */ /* Reconstruct the pixel data using the golden frame reconstruction and change data */ Recon.ReconInter(pbi.ThisFrameRecon, ReconPixelIndex, pbi.GoldenFrame, ReconPixelIndex , ReconDataBuffer, ReconPixelsPerLine ); } else { /* Simple Intra coding */ /* Get the pixel index for the first pixel in the fragment. */ Recon.ReconIntra(pbi.ThisFrameRecon, ReconPixelIndex, ReconDataBuffer, ReconPixelsPerLine ); } } private void UpdateUMV_HBorders( Playback pbi, short[] DestReconPtr, int PlaneFragOffset ) { int i; int PixelIndex; int PlaneStride; int BlockVStep; int PlaneFragments; int LineFragments; int PlaneBorderWidth; int PlaneBorderHeight; short[] SrcPtr1; int SrcOff1; short[] SrcPtr2; int SrcOff2; short[] DestPtr1; int DestOff1; short[] DestPtr2; int DestOff2; /* Work out various plane specific values */ if ( PlaneFragOffset == 0 ) { /* Y Plane */ BlockVStep = (pbi.YStride * (Constants.VFRAGPIXELS - 1)); PlaneStride = pbi.YStride; PlaneBorderWidth = Constants.UMV_BORDER; PlaneBorderHeight = Constants.UMV_BORDER; PlaneFragments = pbi.YPlaneFragments; LineFragments = pbi.HFragments; }else{ /* U or V plane. */ BlockVStep = (pbi.UVStride * (Constants.VFRAGPIXELS - 1)); PlaneStride = pbi.UVStride; PlaneBorderWidth = Constants.UMV_BORDER >> pbi.UVShiftX; PlaneBorderHeight = Constants.UMV_BORDER >> pbi.UVShiftY; PlaneFragments = pbi.UVPlaneFragments; LineFragments = pbi.HFragments >> pbi.UVShiftX; } /* Setup the source and destination pointers for the top and bottom borders */ PixelIndex = pbi.recon_pixel_index_table[PlaneFragOffset]; SrcPtr1 = DestReconPtr; SrcOff1 = PixelIndex - PlaneBorderWidth; DestPtr1 = SrcPtr1; DestOff1 = SrcOff1 - (PlaneBorderHeight * PlaneStride); PixelIndex = pbi.recon_pixel_index_table[PlaneFragOffset + PlaneFragments - LineFragments] + BlockVStep; SrcPtr2 = DestReconPtr; SrcOff2 = PixelIndex - PlaneBorderWidth; DestPtr2 = SrcPtr2; DestOff2 = SrcOff2 + PlaneStride; /* Now copy the top and bottom source lines into each line of the respective borders */ for ( i = 0; i < PlaneBorderHeight; i++ ) { System.arraycopy(SrcPtr1, SrcOff1, DestPtr1, DestOff1, PlaneStride); System.arraycopy(SrcPtr2, SrcOff2, DestPtr2, DestOff2, PlaneStride); DestOff1 += PlaneStride; DestOff2 += PlaneStride; } } private void UpdateUMV_VBorders( Playback pbi, short[] DestReconPtr, int PlaneFragOffset ){ int i; int PixelIndex; int PlaneStride; int LineFragments; int PlaneBorderWidth; int PlaneHeight; short[] SrcPtr1; int SrcOff1; short[] SrcPtr2; int SrcOff2; short[] DestPtr1; int DestOff1; short[] DestPtr2; int DestOff2; /* Work out various plane specific values */ if ( PlaneFragOffset == 0 ) { /* Y Plane */ PlaneStride = pbi.YStride; PlaneBorderWidth = Constants.UMV_BORDER; LineFragments = pbi.HFragments; PlaneHeight = pbi.info.height; }else{ /* U or V plane. */ PlaneStride = pbi.UVStride; PlaneBorderWidth = Constants.UMV_BORDER >> pbi.UVShiftX; LineFragments = pbi.HFragments >> pbi.UVShiftX; PlaneHeight = pbi.info.height >> pbi.UVShiftY; } /* Setup the source data values and destination pointers for the left and right edge borders */ PixelIndex = pbi.recon_pixel_index_table[PlaneFragOffset]; SrcPtr1 = DestReconPtr; SrcOff1 = PixelIndex; DestPtr1 = DestReconPtr; DestOff1 = PixelIndex - PlaneBorderWidth; PixelIndex = pbi.recon_pixel_index_table[PlaneFragOffset + LineFragments - 1] + (Constants.HFRAGPIXELS - 1); SrcPtr2 = DestReconPtr; SrcOff2 = PixelIndex; DestPtr2 = DestReconPtr; DestOff2 = PixelIndex + 1; /* Now copy the top and bottom source lines into each line of the respective borders */ for ( i = 0; i < PlaneHeight; i++ ) { MemUtils.set(DestPtr1, DestOff1, SrcPtr1[SrcOff1], PlaneBorderWidth ); MemUtils.set(DestPtr2, DestOff2, SrcPtr2[SrcOff2], PlaneBorderWidth ); DestOff1 += PlaneStride; DestOff2 += PlaneStride; SrcOff1 += PlaneStride; SrcOff2 += PlaneStride; } } private void UpdateUMVBorder( Playback pbi, short[] DestReconPtr ) { int PlaneFragOffset; /* Y plane */ PlaneFragOffset = 0; UpdateUMV_VBorders( pbi, DestReconPtr, PlaneFragOffset ); UpdateUMV_HBorders( pbi, DestReconPtr, PlaneFragOffset ); /* Then the U and V Planes */ PlaneFragOffset = pbi.YPlaneFragments; UpdateUMV_VBorders( pbi, DestReconPtr, PlaneFragOffset ); UpdateUMV_HBorders( pbi, DestReconPtr, PlaneFragOffset ); PlaneFragOffset = pbi.YPlaneFragments + pbi.UVPlaneFragments; UpdateUMV_VBorders( pbi, DestReconPtr, PlaneFragOffset ); UpdateUMV_HBorders( pbi, DestReconPtr, PlaneFragOffset ); } private void CopyRecon( Playback pbi, short[] DestReconPtr, short[] SrcReconPtr ) { int i; int PlaneLineStep; /* Pixels per line */ int PixelIndex; /* Copy over only updated blocks.*/ /* First Y plane */ PlaneLineStep = pbi.YStride; for ( i = 0; i < pbi.YPlaneFragments; i++ ) { if ( pbi.display_fragments[i] != 0) { PixelIndex = pbi.recon_pixel_index_table[i]; Recon.CopyBlock(SrcReconPtr, DestReconPtr, PixelIndex, PlaneLineStep); } } /* Then U and V */ PlaneLineStep = pbi.UVStride; for ( i = pbi.YPlaneFragments; i < pbi.UnitFragments; i++ ) { if ( pbi.display_fragments[i] != 0) { PixelIndex = pbi.recon_pixel_index_table[i]; Recon.CopyBlock(SrcReconPtr, DestReconPtr, PixelIndex, PlaneLineStep); } } } private void CopyNotRecon( Playback pbi, short[] DestReconPtr, short[] SrcReconPtr ) { int i; int PlaneLineStep; /* Pixels per line */ int PixelIndex; /* Copy over only updated blocks. */ /* First Y plane */ PlaneLineStep = pbi.YStride; for (i = 0; i < pbi.YPlaneFragments; i++) { if (pbi.display_fragments[i] == 0) { PixelIndex = pbi.recon_pixel_index_table[i]; Recon.CopyBlock(SrcReconPtr, DestReconPtr, PixelIndex, PlaneLineStep); } } /* Then U and V */ PlaneLineStep = pbi.UVStride; for (i = pbi.YPlaneFragments; i < pbi.UnitFragments; i++) { if (pbi.display_fragments[i] == 0) { PixelIndex = pbi.recon_pixel_index_table[i]; Recon.CopyBlock(SrcReconPtr, DestReconPtr, PixelIndex, PlaneLineStep); } } } public void ExpandToken( short[] ExpandedBlock, byte[] CoeffIndex, int FragIndex, int Token, int ExtraBits ){ /* Is the token is a combination run and value token. */ if ( Token >= Huffman.DCT_RUN_CATEGORY1 ){ /* Expand the token and additional bits to a zero run length and data value. */ if ( Token < Huffman.DCT_RUN_CATEGORY2 ) { /* Decoding method depends on token */ if ( Token < Huffman.DCT_RUN_CATEGORY1B ) { /* Step on by the zero run length */ CoeffIndex[FragIndex] += (byte)((Token - Huffman.DCT_RUN_CATEGORY1) + 1); /* The extra bit determines the sign. */ ExpandedBlock[CoeffIndex[FragIndex]] = (short)-(((ExtraBits&0x01)<<1)-1); } else if ( Token == Huffman.DCT_RUN_CATEGORY1B ) { /* Bits 0-1 determines the zero run length */ CoeffIndex[FragIndex] += (6 + (ExtraBits & 0x03)); /* Bit 2 determines the sign */ ExpandedBlock[CoeffIndex[FragIndex]] = (short)-(((ExtraBits&0x04)>>1)-1); }else{ /* Bits 0-2 determines the zero run length */ CoeffIndex[FragIndex] += (10 + (ExtraBits & 0x07)); /* Bit 3 determines the sign */ ExpandedBlock[CoeffIndex[FragIndex]] = (short)-(((ExtraBits&0x08)>>2)-1); } }else{ /* If token == Huffman.DCT_RUN_CATEGORY2 we have a single 0 followed by a value */ if ( Token == Huffman.DCT_RUN_CATEGORY2 ){ /* Step on by the zero run length */ CoeffIndex[FragIndex] += 1; /* Bit 1 determines sign, bit 0 the value */ ExpandedBlock[CoeffIndex[FragIndex]] = (short) ((2+(ExtraBits & 0x01)) * -((ExtraBits&0x02)-1)); }else{ /* else we have 2->3 zeros followed by a value */ /* Bit 0 determines the zero run length */ CoeffIndex[FragIndex] += 2 + (ExtraBits & 0x01); /* Bit 2 determines the sign, bit 1 the value */ ExpandedBlock[CoeffIndex[FragIndex]] = (short) ((2+((ExtraBits&0x02)>>1))*-(((ExtraBits&0x04)>>1)-1)); } } /* Step on over value */ CoeffIndex[FragIndex] += 1; } else if ( Token == Huffman.DCT_SHORT_ZRL_TOKEN ) { /* Token is a ZRL token so step on by the appropriate number of zeros */ CoeffIndex[FragIndex] += ExtraBits + 1; } else if ( Token == Huffman.DCT_ZRL_TOKEN ) { /* Token is a ZRL token so step on by the appropriate number of zeros */ CoeffIndex[FragIndex] += ExtraBits + 1; } else if ( Token < Huffman.LOW_VAL_TOKENS ) { /* Token is a small single value token. */ switch ( Token ) { case Huffman.ONE_TOKEN: ExpandedBlock[CoeffIndex[FragIndex]] = 1; break; case Huffman.MINUS_ONE_TOKEN: ExpandedBlock[CoeffIndex[FragIndex]] = -1; break; case Huffman.TWO_TOKEN: ExpandedBlock[CoeffIndex[FragIndex]] = 2; break; case Huffman.MINUS_TWO_TOKEN: ExpandedBlock[CoeffIndex[FragIndex]] = -2; break; } /* Step on the coefficient index. */ CoeffIndex[FragIndex] += 1; }else{ /* Token is a larger single value token */ /* Expand the token and additional bits to a data value. */ if ( Token < Huffman.DCT_VAL_CATEGORY3 ) { /* Offset from LOW_VAL_TOKENS determines value */ Token = Token - Huffman.LOW_VAL_TOKENS; /* Extra bit determines sign */ ExpandedBlock[CoeffIndex[FragIndex]] = (short) ((Token + Huffman.DCT_VAL_CAT2_MIN) * -(((ExtraBits)<<1)-1)); } else if ( Token == Huffman.DCT_VAL_CATEGORY3 ) { /* Bit 1 determines sign, Bit 0 the value */ ExpandedBlock[CoeffIndex[FragIndex]] = (short) ((Huffman.DCT_VAL_CAT3_MIN + (ExtraBits & 0x01)) * -(((ExtraBits&0x02))-1)); } else if ( Token == Huffman.DCT_VAL_CATEGORY4 ) { /* Bit 2 determines sign, Bit 0-1 the value */ ExpandedBlock[CoeffIndex[FragIndex]] = (short) ((Huffman.DCT_VAL_CAT4_MIN + (ExtraBits & 0x03)) * -(((ExtraBits&0x04)>>1)-1)); } else if ( Token == Huffman.DCT_VAL_CATEGORY5 ) { /* Bit 3 determines sign, Bit 0-2 the value */ ExpandedBlock[CoeffIndex[FragIndex]] = (short) ((Huffman.DCT_VAL_CAT5_MIN + (ExtraBits & 0x07)) * -(((ExtraBits&0x08)>>2)-1)); } else if ( Token == Huffman.DCT_VAL_CATEGORY6 ) { /* Bit 4 determines sign, Bit 0-3 the value */ ExpandedBlock[CoeffIndex[FragIndex]] = (short) ((Huffman.DCT_VAL_CAT6_MIN + (ExtraBits & 0x0F)) * -(((ExtraBits&0x10)>>3)-1)); } else if ( Token == Huffman.DCT_VAL_CATEGORY7 ) { /* Bit 5 determines sign, Bit 0-4 the value */ ExpandedBlock[CoeffIndex[FragIndex]] = (short) ((Huffman.DCT_VAL_CAT7_MIN + (ExtraBits & 0x1F)) * -(((ExtraBits&0x20)>>4)-1)); } else if ( Token == Huffman.DCT_VAL_CATEGORY8 ) { /* Bit 9 determines sign, Bit 0-8 the value */ ExpandedBlock[CoeffIndex[FragIndex]] = (short) ((Huffman.DCT_VAL_CAT8_MIN + (ExtraBits & 0x1FF)) * -(((ExtraBits&0x200)>>8)-1)); } /* Step on the coefficient index. */ CoeffIndex[FragIndex] += 1; } } public void ReconRefFrames (Playback pbi){ int i; int j,k,m,n; /* predictor count. */ int pcount; short wpc; short PredictedDC; int FragsAcross=pbi.HFragments; int FromFragment; int FragsDown = pbi.VFragments; int WhichFrame; int WhichCase; boolean isBaseFrame; isBaseFrame = pbi.getFrameType() == Constants.BASE_FRAME; pbi.filter.SetupLoopFilter(pbi.FrameQIndex); /* for y,u,v */ for ( j = 0; j < 3 ; j++) { /* pick which fragments based on Y, U, V */ switch(j){ case 0: /* y */ FromFragment = 0; FragsAcross = pbi.HFragments; FragsDown = pbi.VFragments; break; case 1: /* u */ FromFragment = pbi.YPlaneFragments; FragsAcross = pbi.HFragments >> pbi.UVShiftX; FragsDown = pbi.VFragments >> pbi.UVShiftY; break; /*case 2: v */ default: FromFragment = pbi.YPlaneFragments + pbi.UVPlaneFragments; FragsAcross = pbi.HFragments >> pbi.UVShiftX; FragsDown = pbi.VFragments >> pbi.UVShiftY; break; } /* initialize our array of last used DC Components */ for(k=0;k<3;k++) Last[k]=0; i=FromFragment; /* do prediction on all of Y, U or V */ for ( m = 0 ; m < FragsDown ; m++) { for ( n = 0 ; n < FragsAcross ; n++, i++){ /* only do 2 prediction if fragment coded and on non intra or if all fragments are intra */ if((pbi.display_fragments[i] != 0) || (pbi.getFrameType() == Constants.BASE_FRAME) ){ /* Type of Fragment */ WhichFrame = Mode2Frame[pbi.FragCodingMethod[i].getValue()]; /* Check Borderline Cases */ WhichCase = (n==0?1:0) + ((m==0?1:0) << 1) + ((n+1 == FragsAcross?1:0) << 2); fn[0]=i-1; fn[1]=i-FragsAcross-1; fn[2]=i-FragsAcross; fn[3]=i-FragsAcross+1; /* fragment valid for prediction use if coded and it comes from same frame as the one we are predicting */ for(k=pcount=wpc=0; k<4; k++) { int pflag; pflag=1<>= pc[wpc][4]; } /* check for outranging on the two predictors that can outrange */ if((wpc&(PU|PUL|PL)) == (PU|PUL|PL)){ if(Math.abs(PredictedDC - v[2]) > 128) { PredictedDC = (short)v[2]; } else if( Math.abs(PredictedDC - v[0]) > 128) { PredictedDC = (short)v[0]; } else if( Math.abs(PredictedDC - v[1]) > 128) { PredictedDC = (short)v[1]; } } pbi.QFragData[i][0] += PredictedDC; } /* Save the last fragment coded for whatever frame we are predicting from */ Last[WhichFrame] = pbi.QFragData[i][0]; /* Inverse DCT and reconstitute buffer in thisframe */ if (isBaseFrame) ExpandKFBlock (pbi, i); else ExpandBlock (pbi, i); } } } } /* Copy the current reconstruction back to the last frame recon buffer. */ if(pbi.CodedBlockIndex > (int) (pbi.UnitFragments >> 1)){ short[] SwapReconBuffersTemp = pbi.ThisFrameRecon; pbi.ThisFrameRecon = pbi.LastFrameRecon; pbi.LastFrameRecon = SwapReconBuffersTemp; CopyNotRecon(pbi, pbi.LastFrameRecon, pbi.ThisFrameRecon); }else{ CopyRecon(pbi, pbi.LastFrameRecon, pbi.ThisFrameRecon); } /* Apply a loop filter to edge pixels of updated blocks */ pbi.filter.LoopFilter(pbi); /* We may need to update the UMV border */ UpdateUMVBorder(pbi, pbi.LastFrameRecon); /* Reconstruct the golden frame if necessary. For VFW codec only on key frames */ if (isBaseFrame) { CopyRecon( pbi, pbi.GoldenFrame, pbi.LastFrameRecon ); UpdateUMVBorder(pbi, pbi.GoldenFrame); } } } cortado-0.6.0/src/com/fluendo/jheora/Decode.java100644 0 0 77706 11337276770 16654 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Parts ported from the new Theora C reference encoder, which was mostly * written by Timothy B. Terriberry * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; import com.jcraft.jogg.*; import com.fluendo.utils.*; interface ExtractMVectorComponent { public int extract(Buffer opb); } class ExtractMVectorComponentA implements ExtractMVectorComponent { public int extract (Buffer opb) { /* Get group to which coded component belongs */ /* Now extract the appropriate number of bits to identify the component */ switch (opb.readB(3)){ case 0: return 0; case 1: return 1; case 2: return -1; case 3: return 2 - (4*opb.readB(1)); case 4: return 3 - (6*opb.readB(1)); case 5: return (4 + opb.readB(2)) * -((opb.readB(1)<<1)-1); case 6: return (8 + opb.readB(3)) * -((opb.readB(1)<<1)-1); case 7: return (16 + opb.readB(4)) * -((opb.readB(1)<<1)-1); } return 0; } } class ExtractMVectorComponentB implements ExtractMVectorComponent { public int extract (Buffer opb) { /* Get group to which coded component belongs */ return (opb.readB(5)) * -((opb.readB(1)<<1)-1); } } public final class Decode { private static final ExtractMVectorComponent MVA = new ExtractMVectorComponentA(); private static final ExtractMVectorComponent MVB = new ExtractMVectorComponentB(); private static final CodingMode[][] modeAlphabet = { /* Last motion vector dominates */ { CodingMode.CODE_INTER_LAST_MV, CodingMode.CODE_INTER_PRIOR_LAST, CodingMode.CODE_INTER_PLUS_MV, CodingMode.CODE_INTER_NO_MV, CodingMode.CODE_INTRA, CodingMode.CODE_USING_GOLDEN, CodingMode.CODE_GOLDEN_MV, CodingMode.CODE_INTER_FOURMV }, { CodingMode.CODE_INTER_LAST_MV, CodingMode.CODE_INTER_PRIOR_LAST, CodingMode.CODE_INTER_NO_MV, CodingMode.CODE_INTER_PLUS_MV, CodingMode.CODE_INTRA, CodingMode.CODE_USING_GOLDEN, CodingMode.CODE_GOLDEN_MV, CodingMode.CODE_INTER_FOURMV }, { CodingMode.CODE_INTER_LAST_MV, CodingMode.CODE_INTER_PLUS_MV, CodingMode.CODE_INTER_PRIOR_LAST, CodingMode.CODE_INTER_NO_MV, CodingMode.CODE_INTRA, CodingMode.CODE_USING_GOLDEN, CodingMode.CODE_GOLDEN_MV, CodingMode.CODE_INTER_FOURMV }, { CodingMode.CODE_INTER_LAST_MV, CodingMode.CODE_INTER_PLUS_MV, CodingMode.CODE_INTER_NO_MV, CodingMode.CODE_INTER_PRIOR_LAST, CodingMode.CODE_INTRA, CodingMode.CODE_USING_GOLDEN, CodingMode.CODE_GOLDEN_MV, CodingMode.CODE_INTER_FOURMV }, /* No motion vector dominates */ { CodingMode.CODE_INTER_NO_MV, CodingMode.CODE_INTER_LAST_MV, CodingMode.CODE_INTER_PRIOR_LAST, CodingMode.CODE_INTER_PLUS_MV, CodingMode.CODE_INTRA, CodingMode.CODE_USING_GOLDEN, CodingMode.CODE_GOLDEN_MV, CodingMode.CODE_INTER_FOURMV }, { CodingMode.CODE_INTER_NO_MV, CodingMode.CODE_USING_GOLDEN, CodingMode.CODE_INTER_LAST_MV, CodingMode.CODE_INTER_PRIOR_LAST, CodingMode.CODE_INTER_PLUS_MV, CodingMode.CODE_INTRA, CodingMode.CODE_GOLDEN_MV, CodingMode.CODE_INTER_FOURMV }, /* dummy */ { CodingMode.CODE_INTER_NO_MV, CodingMode.CODE_USING_GOLDEN, CodingMode.CODE_INTER_LAST_MV, CodingMode.CODE_INTER_PRIOR_LAST, CodingMode.CODE_INTER_PLUS_MV, CodingMode.CODE_INTRA, CodingMode.CODE_GOLDEN_MV, CodingMode.CODE_INTER_FOURMV }, }; private int BlocksToDecode; private int EOB_Run; private DCTDecode dctDecode = new DCTDecode(); private byte[] FragCoeffs; /* # of coeffs decoded so far for fragment */ private MotionVector LastInterMV = new MotionVector (); private MotionVector PriorLastInterMV = new MotionVector (); private Playback pbi; public Decode (Playback pbi) { FragCoeffs = new byte[pbi.UnitFragments]; this.pbi = pbi; } private int longRunBitStringDecode() { /* lifted from new C Theora reference decoder */ int bits; int ret; Buffer opb = pbi.opb; /*Coding scheme: Codeword Run Length 0 1 10x 2-3 110x 4-5 1110xx 6-9 11110xxx 10-17 111110xxxx 18-33 111111xxxxxxxxxxxx 34-4129*/ bits = opb.readB(1); if(bits==0)return 1; bits = opb.readB(2); if((bits&2)==0)return 2+(int)bits; else if((bits&1)==0){ bits = opb.readB(1); return 4+(int)bits; } bits = opb.readB(3); if((bits&4)==0)return 6+(int)bits; else if((bits&2)==0){ ret=10+((bits&1)<<2); bits = opb.readB(2); return ret+(int)bits; } else if((bits&1)==0){ bits = opb.readB(4); return 18+(int)bits; } bits = opb.readB(12); return 34+(int)bits; } private void decodeBlockLevelQi() { /* lifted from new C Theora reference decoder */ /* pbi.CodedBlockIndex holds the number of coded blocks despite the suboptimal variable name */ int ncoded_frags = pbi.CodedBlockIndex; if(ncoded_frags <= 0) return; if(pbi.frameNQIS == 1) { /*If this frame has only a single qi value, then just set it in all coded fragments.*/ for(int coded_frag = 0; coded_frag < ncoded_frags; ++coded_frag) { pbi.FragQs[pbi.CodedBlockList[coded_frag]] = 0; } } else{ Buffer opb = pbi.opb; int val; int flag; int nqi0; int run_count; /*Otherwise, we decode a qi index for each fragment, using two passes of the same binary RLE scheme used for super-block coded bits. The first pass marks each fragment as having a qii of 0 or greater than 0, and the second pass (if necessary), distinguishes between a qii of 1 and 2. We store the qii of the fragment. */ val = opb.readB(1); flag = val; run_count = nqi0 = 0; int coded_frag = 0; while(coded_frag < ncoded_frags){ boolean full_run; run_count = longRunBitStringDecode(); full_run = (run_count >= 4129); do { pbi.FragQs[pbi.CodedBlockList[coded_frag++]] = (byte)flag; if(flag < 1) ++nqi0; } while(--run_count > 0 && coded_frag < ncoded_frags); if(full_run && coded_frag < ncoded_frags){ val = opb.readB(1); flag=(int)val; } else { //flag=!flag; flag = (flag != 0) ? 0 : 1; } } /*TODO: run_count should be 0 here. If it's not, we should issue a warning of some kind.*/ /*If we have 3 different qi's for this frame, and there was at least one fragment with a non-zero qi, make the second pass.*/ if(pbi.frameNQIS==3 && nqi0 < ncoded_frags){ coded_frag = 0; /*Skip qii==0 fragments.*/ for(coded_frag = 0; coded_frag < ncoded_frags && pbi.FragQs[pbi.CodedBlockList[coded_frag]] == 0; ++coded_frag){} val = opb.readB(1); flag = val; while(coded_frag < ncoded_frags){ boolean full_run; run_count = longRunBitStringDecode(); full_run = run_count >= 4129; for(; coded_frag < ncoded_frags; ++coded_frag){ if(pbi.FragQs[pbi.CodedBlockList[coded_frag]] == 0) continue; if(run_count-- <= 0) break; pbi.FragQs[pbi.CodedBlockList[coded_frag]] += flag; } if(full_run && coded_frag < ncoded_frags){ val = opb.readB(1); flag = val; } else { //flag=!flag; flag = (flag != 0) ? 0 : 1; } } /*TODO: run_count should be 0 here. If it's not, we should issue a warning of some kind.*/ } } } private int loadFrame() { int DctQMask; Buffer opb = pbi.opb; /* Is the frame and inter frame or a key frame */ pbi.FrameType = (byte)opb.readB(1); /* Quality (Q) index */ DctQMask = (int) opb.readB(6); pbi.frameQIS[0] = DctQMask; pbi.frameNQIS = 1; /* look if there are additional frame quality indices */ int moreQs = opb.readB(1); if(moreQs > 0) { pbi.frameQIS[1] = (int) opb.readB(6); pbi.frameNQIS = 2; moreQs = opb.readB(1); if(moreQs > 0) { pbi.frameQIS[2] = (int) opb.readB(6); pbi.frameNQIS = 3; } } if ( (pbi.FrameType == Constants.BASE_FRAME) ){ /* Read the type / coding method for the key frame. */ pbi.KeyFrameType = (byte)opb.readB(1); opb.readB(2); } /* Set this frame quality value from Q Index */ //pbi.ThisFrameQualityValue = pbi.QThreshTable[pbi.frameQ]; /* Read in the updated block map */ pbi.frArray.quadDecodeDisplayFragments( pbi ); return 1; } private void decodeModes (int SBRows, int SBCols) { int MB; int SBcol; int SBrow; CodingMode[] FragCodingMethod; int SB=0; long ret; int FragIndex; CodingMode CodingMethod; int UVRow; int UVColumn; int UVFragOffset; int MBListIndex = 0; int i; FragCodingMethod = pbi.FragCodingMethod; /* If the frame is an intra frame then all blocks have mode intra. */ if ( pbi.getFrameType() == Constants.BASE_FRAME ){ MemUtils.set(FragCodingMethod, 0, CodingMode.CODE_INTRA, pbi.UnitFragments); }else{ /* Clear down the macro block level mode and MV arrays. Default coding mode */ MemUtils.set(FragCodingMethod, 0, CodingMode.CODE_INTER_NO_MV, pbi.UnitFragments); CodingMode ModeEntry; /* Mode bits read */ CodingMode[] ModeList; /* Read the coding method */ ret = pbi.opb.readB( Constants.MODE_METHOD_BITS); int CodingScheme=(int)ret; /* If the coding method is method 0 then we have to read in a custom coding scheme */ if ( CodingScheme == 0 ){ CodingMode[] CustomModeAlphabet = new CodingMode[Constants.MAX_MODES]; /* Read the coding scheme. */ for ( i = 0; i < Constants.MAX_MODES; i++ ){ ret = pbi.opb.readB( Constants.MODE_BITS); CustomModeAlphabet[(int)ret]= CodingMode.MODES[i]; } ModeList=CustomModeAlphabet; } else{ ModeList=modeAlphabet[CodingScheme-1]; } /* Unravel the quad-tree */ for ( SBrow=0; SBrow= 0){ /* Is the Macro-Block coded: */ if ( pbi.MBCodedFlags[MBListIndex++] != 0){ /* Unpack the mode. */ if ( CodingScheme == (Constants.MODE_METHODS-1) ){ /* This is the fall back coding scheme. */ /* Simply MODE_BITS bits per mode entry. */ ret = pbi.opb.readB( Constants.MODE_BITS); CodingMethod = CodingMode.MODES[(int)ret]; }else{ ModeEntry = pbi.frArray.unpackMode(pbi.opb); CodingMethod = ModeList[ModeEntry.getValue()]; } /* Note the coding mode for each block in macro block. */ FragCodingMethod[FragIndex] = CodingMethod; FragCodingMethod[FragIndex + 1] = CodingMethod; FragCodingMethod[FragIndex + pbi.HFragments] = CodingMethod; FragCodingMethod[FragIndex + pbi.HFragments + 1] = CodingMethod; /* Matching fragments in the U and V planes */ if (pbi.UVShiftX == 1 && pbi.UVShiftY == 1){ /* TH_PF_420 */ UVRow = (FragIndex / (pbi.HFragments * 2)); UVColumn = (FragIndex % pbi.HFragments) / 2; UVFragOffset = (UVRow * (pbi.HFragments / 2)) + UVColumn; FragCodingMethod[pbi.YPlaneFragments + UVFragOffset] = CodingMethod; FragCodingMethod[pbi.YPlaneFragments + pbi.UVPlaneFragments + UVFragOffset] = CodingMethod; } else if (pbi.UVShiftX == 0) { /* TH_PF_444 */ FragIndex += pbi.YPlaneFragments; FragCodingMethod[FragIndex] = FragCodingMethod[FragIndex + 1] = FragCodingMethod[FragIndex + pbi.HFragments] = FragCodingMethod[FragIndex + pbi.HFragments + 1] = CodingMethod; FragIndex += pbi.UVPlaneFragments; FragCodingMethod[FragIndex] = FragCodingMethod[FragIndex + 1] = FragCodingMethod[FragIndex + pbi.HFragments] = FragCodingMethod[FragIndex + pbi.HFragments + 1] = CodingMethod; } else { /*TH_PF_422 */ FragIndex = pbi.YPlaneFragments + FragIndex/2; FragCodingMethod[FragIndex] = FragCodingMethod[FragIndex + pbi.HFragments/2] = CodingMethod; FragIndex += pbi.UVPlaneFragments; FragCodingMethod[FragIndex] = FragCodingMethod[FragIndex + pbi.HFragments/2] = CodingMethod; } } } } /* Next Super-Block */ SB++; } } } } private void decodeMVectors (int SBRows, int SBCols) { int FragIndex; int MB; int SBrow; int SBcol; int SB=0; CodingMode CodingMethod; ExtractMVectorComponent MVC; int UVRow; int UVColumn; int UVFragOffset; int x,y; int MBListIndex = 0; Buffer opb = pbi.opb; /* Should not be decoding motion vectors if in INTRA only mode. */ if (pbi.getFrameType() == Constants.BASE_FRAME ){ return; } MotionVector dummy = new MotionVector(); /* set the default motion vector to 0,0 */ LastInterMV.x = 0; LastInterMV.y = 0; PriorLastInterMV.x = 0; PriorLastInterMV.y = 0; /* Read the entropy method used and set up the appropriate decode option */ if (opb.readB(1) == 0 ) MVC = MVA; else MVC = MVB; /* Unravel the quad-tree */ for ( SBrow=0; SBrow= 0 ) { /* Is the Macro-Block further coded: */ if (pbi.MBCodedFlags[MBListIndex++] != 0){ /* Unpack the mode (and motion vectors if necessary). */ CodingMethod = pbi.FragCodingMethod[FragIndex]; /* Note the coding mode and vector for each block in the current macro block. */ MotionVector MVect0 = pbi.FragMVect[FragIndex]; MotionVector MVect1 = pbi.FragMVect[FragIndex + 1]; MotionVector MVect2 = pbi.FragMVect[FragIndex + pbi.HFragments]; MotionVector MVect3 = pbi.FragMVect[FragIndex + pbi.HFragments + 1]; /* Matching fragments in the U and V planes */ UVRow = (FragIndex / (pbi.HFragments << pbi.UVShiftY)); UVColumn = (FragIndex % pbi.HFragments) >> pbi.UVShiftX; UVFragOffset = (UVRow * (pbi.HFragments >> pbi.UVShiftX)) + UVColumn; MotionVector MVectU0 = pbi.FragMVect[pbi.YPlaneFragments + UVFragOffset]; MotionVector MVectV0 = pbi.FragMVect[pbi.YPlaneFragments + pbi.UVPlaneFragments + UVFragOffset]; MotionVector MVectU1 = dummy; MotionVector MVectV1 = dummy; MotionVector MVectU2 = dummy; MotionVector MVectV2 = dummy; MotionVector MVectU3 = dummy; MotionVector MVectV3 = dummy; if (pbi.UVShiftY == 0) { MVectU2 = pbi.FragMVect[pbi.YPlaneFragments + UVFragOffset + (pbi.HFragments>>pbi.UVShiftX)]; MVectV2 = pbi.FragMVect[pbi.YPlaneFragments + pbi.UVPlaneFragments + UVFragOffset + (pbi.HFragments>>pbi.UVShiftX)]; if (pbi.UVShiftX == 0){ MVectU1 = pbi.FragMVect[pbi.YPlaneFragments + UVFragOffset + 1]; MVectV1 = pbi.FragMVect[pbi.YPlaneFragments + pbi.UVPlaneFragments + UVFragOffset + 1]; MVectU3 = pbi.FragMVect[pbi.YPlaneFragments + UVFragOffset + pbi.HFragments + 1]; MVectV3 = pbi.FragMVect[pbi.YPlaneFragments + pbi.UVPlaneFragments + UVFragOffset + pbi.HFragments + 1]; } } /* Read the motion vector or vectors if present. */ if (CodingMethod == CodingMode.CODE_INTER_PLUS_MV) { PriorLastInterMV.x = LastInterMV.x; PriorLastInterMV.y = LastInterMV.y; LastInterMV.x = MVect0.x = MVect1.x = MVect2.x = MVect3.x = MVectU0.x = MVectV0.x = MVectU1.x = MVectV1.x = MVectU2.x = MVectV2.x = MVectU3.x = MVectV3.x = MVC.extract(opb); LastInterMV.y = MVect0.y = MVect1.y = MVect2.y = MVect3.y = MVectU0.y = MVectV0.y = MVectU1.y = MVectV1.y = MVectU2.y = MVectV2.y = MVectU3.y = MVectV3.y = MVC.extract(opb); } else if (CodingMethod == CodingMode.CODE_GOLDEN_MV){ MVect0.x = MVect1.x = MVect2.x = MVect3.x = MVectU0.x = MVectV0.x = MVectU1.x = MVectV1.x = MVectU2.x = MVectV2.x = MVectU3.x = MVectV3.x = MVC.extract(opb); MVect0.y = MVect1.y = MVect2.y = MVect3.y = MVectU0.y = MVectV0.y = MVectU1.y = MVectV1.y = MVectU2.y = MVectV2.y = MVectU3.y = MVectV3.y = MVC.extract(opb); } else if ( CodingMethod == CodingMode.CODE_INTER_FOURMV ){ /* Update last MV and prior last mv */ PriorLastInterMV.x = LastInterMV.x; PriorLastInterMV.y = LastInterMV.y; /* Extrac the 4 Y MVs */ if(pbi.display_fragments[FragIndex] != 0) { x = MVect0.x = MVC.extract(opb); y = MVect0.y = MVC.extract(opb); LastInterMV.x = MVect0.x; LastInterMV.y = MVect0.y; } else { x = MVect0.x = 0; y = MVect0.y = 0; } if(pbi.display_fragments[FragIndex + 1] != 0) { x += MVect1.x = MVC.extract(opb); y += MVect1.y = MVC.extract(opb); LastInterMV.x = MVect1.x; LastInterMV.y = MVect1.y; } else { x += MVect1.x = 0; y += MVect1.y = 0; } if(pbi.display_fragments[FragIndex + pbi.HFragments] != 0) { x += MVect2.x = MVC.extract(opb); y += MVect2.y = MVC.extract(opb); LastInterMV.x = MVect2.x; LastInterMV.y = MVect2.y; } else { x += MVect2.x = 0; y += MVect2.y = 0; } if(pbi.display_fragments[FragIndex + pbi.HFragments + 1] != 0) { x += MVect3.x = MVC.extract(opb); y += MVect3.y = MVC.extract(opb); LastInterMV.x = MVect3.x; LastInterMV.y = MVect3.y; } else { x += MVect3.x = 0; y += MVect3.y = 0; } if(pbi.UVShiftY == 0) { if(pbi.UVShiftX == 0) { MVectU0.x = MVectV0.x = MVect0.x; MVectU0.y = MVectV0.y = MVect0.y; MVectU1.x = MVectV1.x = MVect1.x; MVectU1.y = MVectV1.y = MVect1.y; MVectU2.x = MVectV2.x = MVect2.x; MVectU2.y = MVectV2.y = MVect2.y; MVectU3.x = MVectV3.x = MVect3.x; MVectU3.y = MVectV3.y = MVect3.y; } else { /* 4:2:2, so average components only horizontally */ x = MVect0.x + MVect1.x; if (x >= 0 ) x = (x+1) / 2; else x = (x-1) / 2; MVectU0.x = MVectV0.x = x; y = MVect0.y + MVect1.y; if (y >= 0 ) y = (y+1) / 2; else y = (y-1) / 2; MVectU0.y = MVectV0.y = y; x = MVect2.x + MVect3.x; if (x >= 0 ) x = (x+1) / 2; else x = (x-1) / 2; MVectU2.x = MVectV2.x = x; y = MVect2.y + MVect3.y; if (y >= 0 ) y = (y+1) / 2; else y = (y-1) / 2; MVectU2.y = MVectV2.y = y; } } else { /* Calculate the U and V plane MVs as the average of the Y plane MVs. */ /* First .x component */ if (x >= 0 ) x = (x+2) / 4; else x = (x-2) / 4; MVectU0.x = x; MVectV0.x = x; /* Then .y component */ if (y >= 0 ) y = (y+2) / 4; else y = (y-2) / 4; MVectU0.y = y; MVectV0.y = y; } } else if ( CodingMethod == CodingMode.CODE_INTER_LAST_MV ){ /* Use the last coded Inter motion vector. */ MVect0.x = MVect1.x = MVect2.x = MVect3.x = MVectU0.x = MVectV0.x = MVectU1.x = MVectV1.x = MVectU2.x = MVectV2.x = MVectU3.x = MVectV3.x = LastInterMV.x; MVect0.y = MVect1.y = MVect2.y = MVect3.y = MVectU0.y = MVectV0.y = MVectU1.y = MVectV1.y = MVectU2.y = MVectV2.y = MVectU3.y = MVectV3.y = LastInterMV.y; } else if ( CodingMethod == CodingMode.CODE_INTER_PRIOR_LAST ){ /* Use the next-to-last coded Inter motion vector. */ MVect0.x = MVect1.x = MVect2.x = MVect3.x = MVectU0.x = MVectV0.x = MVectU1.x = MVectV1.x = MVectU2.x = MVectV2.x = MVectU3.x = MVectV3.x = PriorLastInterMV.x; MVect0.y = MVect1.y = MVect2.y = MVect3.y = MVectU0.y = MVectV0.y = MVectU1.y = MVectV1.y = MVectU2.y = MVectV2.y = MVectU3.y = MVectV3.y = PriorLastInterMV.y; /* Swap the prior and last MV cases over */ MotionVector TmpMVect = PriorLastInterMV; PriorLastInterMV = LastInterMV; LastInterMV = TmpMVect; } else { /* Clear the motion vector else */ MVect0.x = 0; MVect0.y = 0; } } } } /* Next Super-Block */ SB++; } } } private final int ExtractToken(Buffer opb, HuffEntry CurrentRoot){ /* Loop searches down through tree based upon bits read from the bitstream */ /* until it hits a leaf at which point we have decoded a token */ while (CurrentRoot.value < 0 ){ CurrentRoot = CurrentRoot.Child[(int)opb.readB(1)]; } return CurrentRoot.value; } private void unpackAndExpandToken(short[] ExpandedBlock, byte[] CoeffIndex, int FragIndex, int HuffChoice){ int ExtraBits = 0; int Token = ExtractToken(pbi.opb, pbi.HuffRoot_VP3x[HuffChoice]); /* Now.. if we are using the DCT optimised coding system, extract any * assosciated additional bits token. */ if (pbi.ExtraBitLengths_VP3x[Token] > 0){ /* Extract the appropriate number of extra bits. */ ExtraBits = (int)pbi.opb.readB(pbi.ExtraBitLengths_VP3x[Token]); } /* Take token dependant action */ if ( Token >= Huffman.DCT_SHORT_ZRL_TOKEN ) { /* "Value", "zero run" and "zero run value" tokens */ dctDecode.ExpandToken(ExpandedBlock, CoeffIndex, FragIndex, Token, ExtraBits ); if ( CoeffIndex[FragIndex] >= Constants.BLOCK_SIZE ) BlocksToDecode --; }else{ /* Special action and EOB tokens */ switch ( Token ){ case Huffman.DCT_EOB_PAIR_TOKEN: EOB_Run = 1; break; case Huffman.DCT_EOB_TRIPLE_TOKEN: EOB_Run = 2; break; case Huffman.DCT_REPEAT_RUN_TOKEN: EOB_Run = ExtraBits + 3; break; case Huffman.DCT_REPEAT_RUN2_TOKEN: EOB_Run = ExtraBits + 7; break; case Huffman.DCT_REPEAT_RUN3_TOKEN: EOB_Run = ExtraBits + 15; break; case Huffman.DCT_REPEAT_RUN4_TOKEN: EOB_Run = ExtraBits - 1; break; case Huffman.DCT_EOB_TOKEN: break; default: return; } CoeffIndex[FragIndex] = Constants.BLOCK_SIZE; BlocksToDecode --; } } private void unPackVideo () { int EncodedCoeffs = 1; int FragIndex; int AcHuffChoice; int AcHuffChoice1; int AcHuffChoice2; int DcHuffChoice; /* Bail out immediately if a decode error has already been reported. */ if ( pbi.DecoderErrorCode != 0) return; /* Clear down the array that indicates the current coefficient index for each block. */ MemUtils.set(FragCoeffs, 0, 0, pbi.UnitFragments); MemUtils.set(pbi.FragCoefEOB, 0, 0, pbi.UnitFragments); /* Note the number of blocks to decode */ BlocksToDecode = pbi.CodedBlockIndex; /* Get the DC huffman table choice for Y and then UV */ int DcHuffChoice1 = (int)(pbi.opb.readB(Huffman.DC_HUFF_CHOICE_BITS) + Huffman.DC_HUFF_OFFSET); int DcHuffChoice2 = (int)(pbi.opb.readB(Huffman.DC_HUFF_CHOICE_BITS) + Huffman.DC_HUFF_OFFSET); /* UnPack DC coefficients / tokens */ int cbl = 0; int cble = pbi.CodedBlockIndex; while (cbl < cble) { /* Get the block data index */ FragIndex = pbi.CodedBlockList[cbl]; pbi.FragCoefEOB[FragIndex] = FragCoeffs[FragIndex]; /* Select the appropriate huffman table offset according to whether the token is from a Y or UV block */ if (FragIndex < (int)pbi.YPlaneFragments ) DcHuffChoice = DcHuffChoice1; else DcHuffChoice = DcHuffChoice2; /* If we are in the middle of an EOB run */ if ( EOB_Run != 0){ /* Mark the current block as fully expanded and decrement EOB_RUN count */ FragCoeffs[FragIndex] = Constants.BLOCK_SIZE; EOB_Run --; BlocksToDecode --; }else{ /* Else unpack a DC token */ unpackAndExpandToken(pbi.QFragData[FragIndex], FragCoeffs, FragIndex, DcHuffChoice); } cbl++; } /* Get the AC huffman table choice for Y and then for UV. */ int AcHuffIndex1 = (int) (pbi.opb.readB(Huffman.AC_HUFF_CHOICE_BITS) + Huffman.AC_HUFF_OFFSET); int AcHuffIndex2 = (int) (pbi.opb.readB(Huffman.AC_HUFF_CHOICE_BITS) + Huffman.AC_HUFF_OFFSET); /* Unpack Lower AC coefficients. */ while ( EncodedCoeffs < 64 ) { /* Repeatedly scan through the list of blocks. */ cbl = 0; cble = pbi.CodedBlockIndex; /* Huffman table selection based upon which AC coefficient we are on */ if ( EncodedCoeffs <= Huffman.AC_TABLE_2_THRESH ){ AcHuffChoice1 = AcHuffIndex1; AcHuffChoice2 = AcHuffIndex2; }else if ( EncodedCoeffs <= Huffman.AC_TABLE_3_THRESH ){ AcHuffChoice1 = (AcHuffIndex1 + Huffman.AC_HUFF_CHOICES); AcHuffChoice2 = (AcHuffIndex2 + Huffman.AC_HUFF_CHOICES); } else if ( EncodedCoeffs <= Huffman.AC_TABLE_4_THRESH ){ AcHuffChoice1 = (AcHuffIndex1 + (Huffman.AC_HUFF_CHOICES * 2)); AcHuffChoice2 = (AcHuffIndex2 + (Huffman.AC_HUFF_CHOICES * 2)); } else { AcHuffChoice1 = (AcHuffIndex1 + (Huffman.AC_HUFF_CHOICES * 3)); AcHuffChoice2 = (AcHuffIndex2 + (Huffman.AC_HUFF_CHOICES * 3)); } while(cbl < cble ) { /* Get the linear index for the current fragment. */ FragIndex = pbi.CodedBlockList[cbl]; /* Should we decode a token for this block on this pass. */ if ( FragCoeffs[FragIndex] <= EncodedCoeffs ) { pbi.FragCoefEOB[FragIndex] = FragCoeffs[FragIndex]; /* If we are in the middle of an EOB run */ if ( EOB_Run != 0) { /* Mark the current block as fully expanded and decrement EOB_RUN count */ FragCoeffs[FragIndex] = Constants.BLOCK_SIZE; EOB_Run --; BlocksToDecode --; }else{ /* Else unpack an AC token */ /* Work out which huffman table to use, then decode a token */ if ( FragIndex < (int)pbi.YPlaneFragments ) AcHuffChoice = AcHuffChoice1; else AcHuffChoice = AcHuffChoice2; unpackAndExpandToken(pbi.QFragData[FragIndex], FragCoeffs, FragIndex, AcHuffChoice); } } cbl++; } /* Test for condition where there are no blocks left with any tokesn to decode */ if ( BlocksToDecode == 0) break; EncodedCoeffs ++; } } public int loadAndDecode() { int loadFrameOK; /* Load the next frame. */ loadFrameOK = loadFrame(); if (loadFrameOK != 0){ //System.out.println("Load: "+loadFrameOK+" "+pbi.ThisFrameQualityValue+" "+pbi.LastFrameQualityValue); /* Decode the data into the fragment buffer. */ /* Bail out immediately if a decode error has already been reported. */ if (pbi.DecoderErrorCode != 0) return 0; /* Zero Decoder EOB run count */ EOB_Run = 0; /* Make a note of the number of coded blocks this frame */ pbi.CodedBlocksThisFrame = pbi.CodedBlockIndex; /* Decode the modes data */ decodeModes(pbi.YSBRows, pbi.YSBCols); /* Unpack and decode the motion vectors. */ decodeMVectors (pbi.YSBRows, pbi.YSBCols); /* Unpack per-block quantizer information */ decodeBlockLevelQi(); /* Unpack and decode the actual video data. */ unPackVideo(); /* Reconstruct and display the frame */ dctDecode.ReconRefFrames(pbi); return 0; } return(Result.BADPACKET); } } cortado-0.6.0/src/com/fluendo/jheora/Filter.java100644 0 0 32127 11335047750 16672 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; import com.fluendo.utils.*; public final class Filter { /* in-loop filter tables. one of these is used in dct_decode.c */ private static final byte[] LoopFilterLimitValuesV1 = { 30, 25, 20, 20, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* Loop filter bounding values */ private byte[] LoopFilterLimits = new byte[Constants.Q_TABLE_SIZE]; private int[] FiltBoundingValue = new int[512]; private void SetupBoundingValueArray_Generic(int FLimit) { /* Set up the bounding value array. */ MemUtils.set (FiltBoundingValue, 0, 0, 512); for (int i = 0; i < FLimit; i++ ){ FiltBoundingValue[256-i-FLimit] = (-FLimit+i); FiltBoundingValue[256-i] = -i; FiltBoundingValue[256+i] = i; FiltBoundingValue[256+i+FLimit] = FLimit-i; } } /* copy in-loop filter limits from the bitstream header into our instance */ public void copyFilterTables(Info ci) { System.arraycopy(ci.LoopFilterLimitValues, 0, LoopFilterLimits, 0, Constants.Q_TABLE_SIZE); } /* initialize the filter limits from our static table */ public void InitFilterTables() { System.arraycopy(LoopFilterLimitValuesV1, 0, LoopFilterLimits, 0, Constants.Q_TABLE_SIZE); } public void SetupLoopFilter(int FrameQIndex){ int FLimit; /* nb: this was using the V2 values rather than V1 we think is was a mistake; the results were not used */ FLimit = LoopFilterLimits[FrameQIndex]; SetupBoundingValueArray_Generic(FLimit); } private static final short clamp255(int val) { return (short)((~(val>>31)) & 255 & (val | ((255-val)>>31))); } private void FilterHoriz(short[] PixelPtr, int idx, int LineLength, int[] BoundingValuePtr) { int j; int FiltVal; for ( j = 0; j < 8; j++ ){ FiltVal = ( PixelPtr[0 + idx] ) - ( PixelPtr[1 + idx] * 3 ) + ( PixelPtr[2 + idx] * 3 ) - ( PixelPtr[3 + idx] ); FiltVal = BoundingValuePtr[256 + ((FiltVal + 4) >> 3)]; PixelPtr[1 + idx] = clamp255(PixelPtr[1 + idx] + FiltVal); PixelPtr[2 + idx] = clamp255(PixelPtr[2 + idx] - FiltVal); idx += LineLength; } } private void FilterVert(short[] PixelPtr, int idx, int LineLength, int[] BoundingValuePtr){ int j; int FiltVal; /* the math was correct, but negative array indicies are forbidden by ANSI/C99 and will break optimization on several modern compilers */ idx -= 2*LineLength; for ( j = 0; j < 8; j++ ) { FiltVal = ( PixelPtr[idx + 0] ) - ( PixelPtr[idx + LineLength] * 3 ) + ( PixelPtr[idx + 2 * LineLength] * 3 ) - ( PixelPtr[idx + 3 * LineLength] ); FiltVal = BoundingValuePtr[256 + ((FiltVal + 4) >> 3)]; PixelPtr[idx + LineLength] = clamp255(PixelPtr[idx + LineLength] + FiltVal); PixelPtr[idx + 2 * LineLength] = clamp255(PixelPtr[idx + 2*LineLength] - FiltVal); idx++; } } public void LoopFilter(Playback pbi){ int FragsAcross=pbi.HFragments; int FromFragment; int FragsDown = pbi.VFragments; int LineFragments; int LineLength; int FLimit; int QIndex; int i,j,m,n; int index; /* Set the limit value for the loop filter based upon the current quantizer. */ QIndex = pbi.frameQIS[0]; FLimit = LoopFilterLimits[QIndex]; if ( FLimit == 0 ) return; SetupBoundingValueArray_Generic(FLimit); for ( j = 0; j < 3 ; j++){ switch(j) { case 0: /* y */ FromFragment = 0; FragsAcross = pbi.HFragments; FragsDown = pbi.VFragments; LineLength = pbi.YStride; LineFragments = pbi.HFragments; break; case 1: /* u */ FromFragment = pbi.YPlaneFragments; FragsAcross = pbi.HFragments >> 1; FragsDown = pbi.VFragments >> 1; LineLength = pbi.UVStride; LineFragments = pbi.HFragments / 2; break; /*case 2: v */ default: FromFragment = pbi.YPlaneFragments + pbi.UVPlaneFragments; FragsAcross = pbi.HFragments >> 1; FragsDown = pbi.VFragments >> 1; LineLength = pbi.UVStride; LineFragments = pbi.HFragments / 2; break; } i=FromFragment; /************************************************************** First Row **************************************************************/ /* first column conditions */ /* only do 2 prediction if fragment coded and on non intra or if all fragments are intra */ if( pbi.display_fragments[i] != 0){ /* Filter right hand border only if the block to the right is not coded */ if ( pbi.display_fragments[ i + 1 ] == 0){ FilterHoriz(pbi.LastFrameRecon, pbi.recon_pixel_index_table[i]+6, LineLength,FiltBoundingValue); } /* Bottom done if next row set */ if( pbi.display_fragments[ i + LineFragments] == 0){ FilterVert(pbi.LastFrameRecon, pbi.recon_pixel_index_table[i+LineFragments], LineLength, FiltBoundingValue); } } i++; /***************************************************************/ /* middle columns */ for ( n = 1 ; n < FragsAcross - 1 ; n++) { if( pbi.display_fragments[i] != 0){ index = pbi.recon_pixel_index_table[i]; /* Filter Left edge always */ FilterHoriz(pbi.LastFrameRecon, index-2, LineLength, FiltBoundingValue); /* Filter right hand border only if the block to the right is not coded */ if (pbi.display_fragments[ i + 1 ] == 0){ FilterHoriz(pbi.LastFrameRecon, index+6, LineLength, FiltBoundingValue); } /* Bottom done if next row set */ if(pbi.display_fragments[ i + LineFragments] == 0){ FilterVert(pbi.LastFrameRecon, pbi.recon_pixel_index_table[i+LineFragments], LineLength, FiltBoundingValue); } } i++; } /***************************************************************/ /* Last Column */ if( pbi.display_fragments[i] != 0){ /* Filter Left edge always */ FilterHoriz(pbi.LastFrameRecon, pbi.recon_pixel_index_table[i] - 2 , LineLength, FiltBoundingValue); /* Bottom done if next row set */ if(pbi.display_fragments[ i + LineFragments] == 0){ FilterVert(pbi.LastFrameRecon, pbi.recon_pixel_index_table[i+LineFragments], LineLength, FiltBoundingValue); } } i++; /***************************************************************/ /* Middle Rows */ /***************************************************************/ for ( m = 1 ; m < FragsDown-1 ; m++) { /*****************************************************************/ /* first column conditions */ /* only do 2 prediction if fragment coded and on non intra or if all fragments are intra */ if(pbi.display_fragments[i] != 0){ index = pbi.recon_pixel_index_table[i]; /* TopRow is always done */ FilterVert(pbi.LastFrameRecon, index, LineLength, FiltBoundingValue); /* Filter right hand border only if the block to the right is not coded */ if (pbi.display_fragments[ i + 1 ] == 0){ FilterHoriz(pbi.LastFrameRecon, index + 6, LineLength, FiltBoundingValue); } /* Bottom done if next row set */ if(pbi.display_fragments[ i + LineFragments] == 0){ FilterVert(pbi.LastFrameRecon, pbi.recon_pixel_index_table[i+LineFragments], LineLength, FiltBoundingValue); } } i++; /*****************************************************************/ /* middle columns */ for ( n = 1 ; n < FragsAcross - 1 ; n++, i++){ if( pbi.display_fragments[i] != 0){ index = pbi.recon_pixel_index_table[i]; /* Filter Left edge always */ FilterHoriz(pbi.LastFrameRecon, index - 2, LineLength, FiltBoundingValue); /* TopRow is always done */ FilterVert(pbi.LastFrameRecon, index, LineLength, FiltBoundingValue); /* Filter right hand border only if the block to the right is not coded */ if (pbi.display_fragments[ i + 1 ] == 0){ FilterHoriz(pbi.LastFrameRecon, index + 6, LineLength, FiltBoundingValue); } /* Bottom done if next row set */ if(pbi.display_fragments[ i + LineFragments] == 0){ FilterVert(pbi.LastFrameRecon, pbi.recon_pixel_index_table[i+LineFragments], LineLength, FiltBoundingValue); } } } /******************************************************************/ /* Last Column */ if( pbi.display_fragments[i] != 0){ index = pbi.recon_pixel_index_table[i]; /* Filter Left edge always*/ FilterHoriz(pbi.LastFrameRecon, index - 2, LineLength, FiltBoundingValue); /* TopRow is always done */ FilterVert(pbi.LastFrameRecon, index, LineLength, FiltBoundingValue); /* Bottom done if next row set */ if(pbi.display_fragments[ i + LineFragments] == 0){ FilterVert(pbi.LastFrameRecon, pbi.recon_pixel_index_table[i+LineFragments], LineLength, FiltBoundingValue); } } i++; } /*******************************************************************/ /* Last Row */ /* first column conditions */ /* only do 2 prediction if fragment coded and on non intra or if all fragments are intra */ if(pbi.display_fragments[i] != 0){ index = pbi.recon_pixel_index_table[i]; /* TopRow is always done */ FilterVert(pbi.LastFrameRecon, index, LineLength, FiltBoundingValue); /* Filter right hand border only if the block to the right is not coded */ if (pbi.display_fragments[ i + 1 ] == 0){ FilterHoriz(pbi.LastFrameRecon, index+6, LineLength, FiltBoundingValue); } } i++; /******************************************************************/ /* middle columns */ for ( n = 1 ; n < FragsAcross - 1 ; n++, i++){ if( pbi.display_fragments[i] != 0){ index = pbi.recon_pixel_index_table[i]; /* Filter Left edge always */ FilterHoriz(pbi.LastFrameRecon, index-2, LineLength, FiltBoundingValue); /* TopRow is always done */ FilterVert(pbi.LastFrameRecon, index, LineLength, FiltBoundingValue); /* Filter right hand border only if the block to the right is not coded */ if (pbi.display_fragments[ i + 1 ] == 0){ FilterHoriz(pbi.LastFrameRecon, index+6, LineLength, FiltBoundingValue); } } } /******************************************************************/ /* Last Column */ if(pbi.display_fragments[i] != 0){ index = pbi.recon_pixel_index_table[i]; /* Filter Left edge always */ FilterHoriz(pbi.LastFrameRecon, index - 2, LineLength, FiltBoundingValue); /* TopRow is always done */ FilterVert(pbi.LastFrameRecon, index, LineLength, FiltBoundingValue); } } } } cortado-0.6.0/src/com/fluendo/jheora/FrArray.java100644 0 0 25475 11274362076 17026 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; import com.jcraft.jogg.*; import com.fluendo.utils.*; public class FrArray { private int bit_pattern; private byte bits_so_far; private byte NextBit; private int BitsLeft; public FrArray() { } public void init() { /* Initialise the decoding of a run. */ bit_pattern = 0; bits_so_far = 0; } private int deCodeBlockRun(int bit_value){ /* Add in the new bit value. */ bits_so_far++; bit_pattern = (bit_pattern << 1) + (bit_value & 1); /* Coding scheme: Codeword RunLength 0x 1-2 10x 3-4 110x 5-6 1110xx 7-10 11110xx 11-14 11111xxxx 15-30 */ switch ( bits_so_far ){ case 2: /* If bit 1 is clear */ if ((bit_pattern & 0x0002) == 0){ BitsLeft = (bit_pattern & 0x0001) + 1; return 1; } break; case 3: /* If bit 1 is clear */ if ((bit_pattern & 0x0002) == 0){ BitsLeft = (bit_pattern & 0x0001) + 3; return 1; } break; case 4: /* If bit 1 is clear */ if ((bit_pattern & 0x0002) == 0){ BitsLeft = (bit_pattern & 0x0001) + 5; return 1; } break; case 6: /* If bit 2 is clear */ if ((bit_pattern & 0x0004) == 0){ BitsLeft = (bit_pattern & 0x0003) + 7; return 1; } break; case 7: /* If bit 2 is clear */ if ((bit_pattern & 0x0004) == 0){ BitsLeft = (bit_pattern & 0x0003) + 11; return 1; } break; case 9: BitsLeft = (bit_pattern & 0x000F) + 15; return 1; } return 0; } private int deCodeSBRun (int bit_value){ /* Add in the new bit value. */ bits_so_far++; bit_pattern = (bit_pattern << 1) + (bit_value & 1); /* Coding scheme: Codeword RunLength 0 1 10x 2-3 110x 4-5 1110xx 6-9 11110xxx 10-17 111110xxxx 18-33 111111xxxxxxxxxxxx 34-4129 */ switch ( bits_so_far ){ case 1: if (bit_pattern == 0 ){ BitsLeft = 1; return 1; } break; case 3: /* Bit 1 clear */ if ((bit_pattern & 0x0002) == 0){ BitsLeft = (bit_pattern & 0x0001) + 2; return 1; } break; case 4: /* Bit 1 clear */ if ((bit_pattern & 0x0002) == 0){ BitsLeft = (bit_pattern & 0x0001) + 4; return 1; } break; case 6: /* Bit 2 clear */ if ((bit_pattern & 0x0004) == 0){ BitsLeft = (bit_pattern & 0x0003) + 6; return 1; } break; case 8: /* Bit 3 clear */ if ((bit_pattern & 0x0008) == 0){ BitsLeft = (bit_pattern & 0x0007) + 10; return 1; } break; case 10: /* Bit 4 clear */ if ((bit_pattern & 0x0010) == 0){ BitsLeft = (bit_pattern & 0x000F) + 18; return 1; } break; case 18: BitsLeft = (bit_pattern & 0x0FFF) + 34; return 1; } return 0; } private void getNextBInit(Buffer opb){ long ret; ret = opb.readB(1); NextBit = (byte)ret; /* Read run length */ init(); do { ret = opb.readB(1); } while (deCodeBlockRun((int)ret)==0); } private byte getNextBBit (Buffer opb){ long ret; if (BitsLeft == 0){ /* Toggle the value. */ NextBit = (byte) (NextBit ^ 1); /* Read next run */ init(); do { ret = opb.readB(1); } while (deCodeBlockRun((int)ret)==0); } /* Have read a bit */ BitsLeft--; /* Return next bit value */ return NextBit; } private void getNextSbInit(Buffer opb){ long ret; ret = opb.readB(1); NextBit = (byte)ret; /* Read run length */ init(); do { ret = opb.readB(1); } while (deCodeSBRun((int)ret)==0); } private byte getNextSbBit (Buffer opb){ long ret; if (BitsLeft == 0){ /* Toggle the value. */ NextBit = (byte) (NextBit ^ 1); /* Read next run */ init(); do { ret = opb.readB(1); } while (deCodeSBRun((int)ret)==0); } /* Have read a bit */ BitsLeft--; /* Return next bit value */ return NextBit; } private final short[] empty64 = new short[64]; public void quadDecodeDisplayFragments ( Playback pbi ){ int SB, MB, B; int DataToDecode; int dfIndex; int MBIndex = 0; Buffer opb = pbi.opb; /* Reset various data structures common to key frames and inter frames. */ pbi.CodedBlockIndex = 0; MemUtils.set ( pbi.display_fragments, 0, 0, pbi.UnitFragments ); /* For "Key frames" mark all blocks as coded and return. */ /* Else initialise the ArrayPtr array to 0 (all blocks uncoded by default) */ if ( pbi.getFrameType() == Constants.BASE_FRAME ) { MemUtils.set( pbi.SBFullyFlags, 0, 1, pbi.SuperBlocks ); MemUtils.set( pbi.SBCodedFlags, 0, 1, pbi.SuperBlocks ); MemUtils.set( pbi.MBCodedFlags, 0, 0, pbi.MacroBlocks ); }else{ MemUtils.set( pbi.SBFullyFlags, 0, 0, pbi.SuperBlocks ); MemUtils.set( pbi.MBCodedFlags, 0, 0, pbi.MacroBlocks ); /* Un-pack the list of partially coded Super-Blocks */ getNextSbInit(opb); for( SB = 0; SB < pbi.SuperBlocks; SB++){ pbi.SBCodedFlags[SB] = getNextSbBit (opb); } /* Scan through the list of super blocks. Unless all are marked as partially coded we have more to do. */ DataToDecode = 0; for ( SB=0; SB= 0 ){ /* Only read block level data if SB was fully or partially coded */ if (pbi.SBCodedFlags[SB] != 0) { for ( B=0; B<4; B++ ){ /* If block is valid (in frame)... */ dfIndex = pbi.BlockMap.quadMapToIndex1(SB, MB, B); if ( dfIndex >= 0 ){ if ( pbi.SBFullyFlags[SB] != 0) pbi.display_fragments[dfIndex] = 1; else pbi.display_fragments[dfIndex] = getNextBBit(opb); /* Create linear list of coded block indices */ if ( pbi.display_fragments[dfIndex] != 0) { pbi.MBCodedFlags[MBIndex] = 1; pbi.CodedBlockList[pbi.CodedBlockIndex] = dfIndex; /* Clear down the pbi.QFragData structure for this coded block. */ System.arraycopy(empty64, 0, pbi.QFragData[dfIndex], 0, 64); pbi.CodedBlockIndex++; } } } } MBIndex++; } } } } public CodingMode unpackMode(Buffer opb){ /* Coding scheme: Token Codeword Bits Entry 0 (most frequent) 0 1 Entry 1 10 2 Entry 2 110 3 Entry 3 1110 4 Entry 4 11110 5 Entry 5 111110 6 Entry 6 1111110 7 Entry 7 1111111 7 */ /* Initialise the decoding. */ bits_so_far = 0; bit_pattern = (int) opb.readB(1); /* Do we have a match */ if ( bit_pattern == 0 ) return CodingMode.MODES[0]; /* Get the next bit */ bit_pattern = (bit_pattern << 1) | (int)opb.readB(1); /* Do we have a match */ if ( bit_pattern == 0x0002 ) return CodingMode.MODES[1]; bit_pattern = (bit_pattern << 1) | (int)opb.readB(1); /* Do we have a match */ if ( bit_pattern == 0x0006 ) return CodingMode.MODES[2]; bit_pattern = (bit_pattern << 1) | (int)opb.readB(1); /* Do we have a match */ if ( bit_pattern == 0x000E ) return CodingMode.MODES[3]; bit_pattern = (bit_pattern << 1) | (int)opb.readB(1); /* Do we have a match */ if ( bit_pattern == 0x001E ) return CodingMode.MODES[4]; bit_pattern = (bit_pattern << 1) | (int)opb.readB(1); /* Do we have a match */ if ( bit_pattern == 0x003E ) return CodingMode.MODES[5]; bit_pattern = (bit_pattern << 1) | (int)opb.readB(1); /* Do we have a match */ if ( bit_pattern == 0x007E ) return CodingMode.MODES[6]; else return CodingMode.MODES[7]; } } cortado-0.6.0/src/com/fluendo/jheora/FrInit.java100644 0 0 23265 11336021765 16642 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; public class FrInit { static void InitializeFragCoordinates(Playback pbi) { int i, j; int HorizFrags = pbi.HFragments; int VertFrags = pbi.VFragments; int StartFrag = 0; /* Y */ for(i = 0; i< VertFrags; i++){ for(j = 0; j< HorizFrags; j++){ int ThisFrag = i * HorizFrags + j; pbi.FragCoordinates[ ThisFrag ] = new Coordinate(j * Constants.BLOCK_HEIGHT_WIDTH, i * Constants.BLOCK_HEIGHT_WIDTH); } } /* U */ HorizFrags >>= pbi.UVShiftX; VertFrags >>= pbi.UVShiftY; StartFrag = pbi.YPlaneFragments; for(i = 0; i< VertFrags; i++) { for(j = 0; j< HorizFrags; j++) { int ThisFrag = StartFrag + i * HorizFrags + j; pbi.FragCoordinates[ ThisFrag ] = new Coordinate(j * Constants.BLOCK_HEIGHT_WIDTH, i * Constants.BLOCK_HEIGHT_WIDTH); } } /* V */ StartFrag = pbi.YPlaneFragments + pbi.UVPlaneFragments; for(i = 0; i< VertFrags; i++) { for(j = 0; j< HorizFrags; j++) { int ThisFrag = StartFrag + i * HorizFrags + j; pbi.FragCoordinates[ ThisFrag ] = new Coordinate(j * Constants.BLOCK_HEIGHT_WIDTH, i * Constants.BLOCK_HEIGHT_WIDTH); } } } static void CalcPixelIndexTable(Playback pbi){ int i, off; int[] PixelIndexTablePtr; /* Calculate the pixel index table for normal image buffers */ PixelIndexTablePtr = pbi.pixel_index_table; for ( i = 0; i < pbi.YPlaneFragments; i++ ) { PixelIndexTablePtr[ i ] = ((i / pbi.HFragments) * Constants.VFRAGPIXELS * pbi.info.width); PixelIndexTablePtr[ i ] += ((i % pbi.HFragments) * Constants.HFRAGPIXELS); } off = pbi.YPlaneFragments; for ( i = 0; i < ((pbi.HFragments >> pbi.UVShiftX) * pbi.VFragments); i++ ) { PixelIndexTablePtr[ i + off] = ((i / (pbi.HFragments >> pbi.UVShiftX) ) * (Constants.VFRAGPIXELS * (pbi.info.width >> pbi.UVShiftX)) ); PixelIndexTablePtr[ i + off] += ((i % (pbi.HFragments >> pbi.UVShiftX) ) * Constants.HFRAGPIXELS) + pbi.YPlaneSize; } /************************************************************************/ /* Now calculate the pixel index table for image reconstruction buffers */ PixelIndexTablePtr = pbi.recon_pixel_index_table; for ( i = 0; i < pbi.YPlaneFragments; i++ ){ PixelIndexTablePtr[ i ] = ((i / pbi.HFragments) * Constants.VFRAGPIXELS * pbi.YStride); PixelIndexTablePtr[ i ] += ((i % pbi.HFragments) * Constants.HFRAGPIXELS) + pbi.ReconYDataOffset; } /* U blocks */ off = pbi.YPlaneFragments; for ( i = 0; i < pbi.UVPlaneFragments; i++ ) { PixelIndexTablePtr[i+off] = ((i / (pbi.HFragments >> pbi.UVShiftX) ) * (Constants.VFRAGPIXELS * (pbi.UVStride)) ); PixelIndexTablePtr[i+off] += ((i % (pbi.HFragments >> pbi.UVShiftX) ) * Constants.HFRAGPIXELS) + pbi.ReconUDataOffset; } /* V blocks */ off = pbi.YPlaneFragments + pbi.UVPlaneFragments; for ( i = 0; i < pbi.UVPlaneFragments; i++ ) { PixelIndexTablePtr[ i +off] = ((i / (pbi.HFragments >> pbi.UVShiftX) ) * (Constants.VFRAGPIXELS * (pbi.UVStride)) ); PixelIndexTablePtr[ i +off] += ((i % (pbi.HFragments >> pbi.UVShiftX) ) * Constants.HFRAGPIXELS) + pbi.ReconVDataOffset; } } static void ClearFragmentInfo(Playback pbi){ /* free prior allocs if present */ pbi.display_fragments = null; pbi.pixel_index_table = null; pbi.recon_pixel_index_table = null; pbi.FragTokenCounts = null; pbi.CodedBlockList = null; pbi.FragMVect = null; pbi.FragCoefEOB = null; pbi.QFragData = null; pbi.FragCodingMethod = null; pbi.FragCoordinates = null; pbi.FragQIndex = null; pbi.BlockMap = null; pbi.SBCodedFlags = null; pbi.SBFullyFlags = null; pbi.MBFullyFlags = null; pbi.MBCodedFlags = null; } static void InitFragmentInfo(Playback pbi){ /* clear any existing info */ ClearFragmentInfo(pbi); /* Perform Fragment Allocations */ pbi.display_fragments = new byte[pbi.UnitFragments]; pbi.pixel_index_table = new int[pbi.UnitFragments]; pbi.recon_pixel_index_table = new int[pbi.UnitFragments]; pbi.FragTokenCounts = new int[pbi.UnitFragments]; pbi.CodedBlockList = new int[pbi.UnitFragments]; pbi.FragMVect = new MotionVector[pbi.UnitFragments]; for (int i=0; i> pbi.UVShiftX; pbi.ReconYPlaneSize = pbi.YStride * (pbi.info.height + Constants.STRIDE_EXTRA); pbi.ReconUVPlaneSize = pbi.ReconYPlaneSize / uv_fact; FrameSize = pbi.ReconYPlaneSize + 2 * pbi.ReconUVPlaneSize; pbi.YDataOffset = 0; pbi.UDataOffset = pbi.YPlaneSize; pbi.VDataOffset = pbi.YPlaneSize + pbi.UVPlaneSize; pbi.ReconYDataOffset = (pbi.YStride * Constants.UMV_BORDER) + Constants.UMV_BORDER; pbi.ReconUDataOffset = pbi.ReconYPlaneSize + (pbi.UVStride * (Constants.UMV_BORDER>>pbi.UVShiftY)) + (Constants.UMV_BORDER>>pbi.UVShiftX); pbi.ReconVDataOffset = pbi.ReconYPlaneSize + pbi.ReconUVPlaneSize + (pbi.UVStride * (Constants.UMV_BORDER>>pbi.UVShiftY)) + (Constants.UMV_BORDER>>pbi.UVShiftX); /* Image dimensions in Super-Blocks */ pbi.YSBRows = (pbi.info.height/32) + ( pbi.info.height%32 !=0 ? 1 : 0 ); pbi.YSBCols = (pbi.info.width/32) + ( pbi.info.width%32 !=0 ? 1 : 0 ); pbi.UVSBRows = ((pbi.info.height>>pbi.UVShiftY)/32) + ( (pbi.info.height>>pbi.UVShiftY)%32 !=0 ? 1 : 0 ); pbi.UVSBCols = ((pbi.info.width>>pbi.UVShiftX)/32) + ( (pbi.info.width>>pbi.UVShiftX)%32 !=0 ? 1 : 0 ); /* Super-Blocks per component */ pbi.YSuperBlocks = pbi.YSBRows * pbi.YSBCols; pbi.UVSuperBlocks = pbi.UVSBRows * pbi.UVSBCols; pbi.SuperBlocks = pbi.YSuperBlocks+2*pbi.UVSuperBlocks; /* Useful externals */ pbi.YMacroBlocks = ((pbi.VFragments+1)/2)*((pbi.HFragments+1)/2); pbi.UVMacroBlocks = (((pbi.VFragments>>pbi.UVShiftY)+1)/2)*(((pbi.HFragments>>pbi.UVShiftX)+1)/2); pbi.MacroBlocks = pbi.YMacroBlocks+2*pbi.UVMacroBlocks; InitFragmentInfo(pbi); InitFrameInfo(pbi, FrameSize); InitializeFragCoordinates(pbi); /* Configure mapping between quad-tree and fragments */ pbi.BlockMap = new BlockMapping (pbi.YSuperBlocks, pbi.UVSuperBlocks, pbi.HFragments, pbi.VFragments, pbi.UVShiftX, pbi.UVShiftY); /* Re-initialise the pixel index table. */ CalcPixelIndexTable( pbi ); } } cortado-0.6.0/src/com/fluendo/jheora/HuffEntry.java100644 0 0 4027 11270111317 17322 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; import com.jcraft.jogg.*; public class HuffEntry { HuffEntry[] Child = new HuffEntry[2]; HuffEntry previous; HuffEntry next; int value; int frequency; public HuffEntry copy() { HuffEntry huffDst; huffDst = new HuffEntry(); huffDst.value = value; if (value < 0) { huffDst.Child[0] = Child[0].copy(); huffDst.Child[1] = Child[1].copy(); } return huffDst; } public int read(int depth, Buffer opb) { int bit; int ret; bit = opb.readB(1); if(bit < 0) { return Result.BADHEADER; } else if(bit == 0) { if (++depth > 32) return Result.BADHEADER; Child[0] = new HuffEntry(); ret = Child[0].read(depth, opb); if (ret < 0) return ret; Child[1] = new HuffEntry(); ret = Child[1].read(depth, opb); if (ret < 0) return ret; value = -1; } else { Child[0] = null; Child[1] = null; value = opb.readB(5); if (value < 0) return Result.BADHEADER; } return 0; } } cortado-0.6.0/src/com/fluendo/jheora/HuffTables.java100644 0 0 50064 11270111317 17455 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; public class HuffTables { static final byte[] ExtraBitLengths_VP31 = { 0, 0, 0, 2, 3, 4, 12,3, 6, /* EOB and Zero-run tokens. */ 0, 0, 0, 0, /* Very low value tokens. */ 1, 1, 1, 1, 2, 3, 4, 5, 6, 10, /* Other value tokens */ 1, 1, 1, 1, 1, 3, 4, /* Category 1 runs. */ 2, 3, /* Category 2 runs. */ }; static final short[][] FrequencyCounts_VP3 = { /* DC Intra bias */ { 198, 62, 22, 31, 14, 6, 6, 205, 3, 843, 843, 415, 516, 660, 509, 412, 347, 560, 779, 941, 930, 661, 377, 170, 155, 39, 2, 9, 15, 11, 128, 86, }, { 299, 92, 34, 39, 15, 6, 6, 132, 1, 851, 851, 484, 485, 666, 514, 416, 351, 567, 788, 953, 943, 670, 383, 117, 119, 26, 4, 17, 7, 1, 93, 56, }, { 367, 115, 42, 47, 16, 6, 6, 105, 1, 896, 896, 492, 493, 667, 510, 408, 342, 547, 760, 932, 927, 656, 379, 114, 103, 10, 3, 6, 2, 1, 88, 49, }, { 462, 158, 63, 76, 28, 9, 8, 145, 1, 1140, 1140, 573, 574, 754, 562, 435, 357, 555, 742, 793, 588, 274, 81, 154, 117, 13, 6, 12, 2, 1, 104, 62, }, { 558, 196, 81, 99, 36, 11, 9, 135, 1, 1300, 1301, 606, 607, 779, 560, 429, 349, 536, 680, 644, 405, 153, 30, 171, 120, 12, 5, 14, 3, 1, 104, 53, }, { 635, 233, 100, 122, 46, 14, 12, 113, 1, 1414, 1415, 631, 631, 785, 555, 432, 335, 513, 611, 521, 284, 89, 13, 170, 113, 10, 5, 14, 3, 1, 102, 62, }, { 720, 276, 119, 154, 62, 20, 16, 101, 1, 1583, 1583, 661, 661, 794, 556, 407, 318, 447, 472, 343, 153, 35, 1, 172, 115, 11, 7, 14, 3, 1, 112, 70, }, { 853, 326, 144, 184, 80, 27, 19, 52, 1, 1739, 1740, 684, 685, 800, 540, 381, 277, 364, 352, 218, 78, 13, 1, 139, 109, 9, 6, 20, 2, 1, 94, 50, }, /* DC Inter Bias */ { 490, 154, 57, 53, 10, 2, 1, 238, 160, 1391, 1390, 579, 578, 491, 273, 172, 118, 152, 156, 127, 79, 41, 39, 712, 547, 316, 125, 183, 306, 237, 451, 358, }, { 566, 184, 70, 65, 11, 2, 1, 235, 51, 1414, 1414, 599, 598, 510, 285, 180, 124, 157, 161, 131, 82, 42, 40, 738, 551, 322, 138, 195, 188, 93, 473, 365, }, { 711, 261, 111, 126, 27, 4, 1, 137, 52, 1506, 1505, 645, 645, 567, 316, 199, 136, 172, 175, 142, 88, 45, 48, 548, 449, 255, 145, 184, 174, 121, 260, 227, }, { 823, 319, 144, 175, 43, 7, 1, 53, 42, 1648, 1648, 653, 652, 583, 329, 205, 139, 175, 176, 139, 84, 44, 34, 467, 389, 211, 137, 181, 186, 107, 106, 85, }, { 948, 411, 201, 276, 85, 16, 2, 39, 33, 1778, 1777, 584, 583, 489, 265, 162, 111, 140, 140, 108, 64, 38, 23, 428, 356, 201, 139, 186, 165, 94, 78, 63, }, { 1002, 470, 248, 386, 153, 39, 6, 23, 23, 1866, 1866, 573, 573, 467, 249, 155, 103, 130, 128, 94, 60, 38, 14, 323, 263, 159, 111, 156, 153, 74, 46, 34, }, { 1020, 518, 291, 504, 242, 78, 18, 14, 14, 1980, 1979, 527, 526, 408, 219, 132, 87, 110, 104, 79, 55, 31, 7, 265, 213, 129, 91, 131, 111, 50, 31, 20, }, { 1018, 544, 320, 591, 338, 139, 47, 5, 2, 2123, 2123, 548, 547, 414, 212, 126, 83, 101, 96, 79, 60, 23, 1, 120, 97, 55, 39, 60, 38, 15, 11, 8, }, /* AC INTRA Tables */ /* AC Intra bias group 1 tables */ { 242, 62, 22, 20, 4, 1, 1, 438, 1, 593, 593, 489, 490, 657, 580, 471, 374, 599, 783, 869, 770, 491, 279, 358, 144, 82, 54, 49, 70, 5, 289, 107, }, { 317, 95, 38, 41, 8, 1, 1, 479, 1, 653, 654, 500, 501, 682, 611, 473, 376, 582, 762, 806, 656, 358, 155, 419, 162, 86, 58, 36, 34, 1, 315, 126, }, { 382, 121, 49, 59, 15, 3, 1, 496, 1, 674, 674, 553, 554, 755, 636, 487, 391, 576, 718, 701, 488, 221, 72, 448, 161, 107, 56, 37, 29, 1, 362, 156, }, { 415, 138, 57, 73, 21, 5, 1, 528, 1, 742, 741, 562, 563, 753, 669, 492, 388, 563, 664, 589, 340, 129, 26, 496, 184, 139, 71, 48, 33, 2, 387, 166, }, { 496, 170, 73, 94, 31, 8, 2, 513, 1, 855, 855, 604, 604, 769, 662, 477, 356, 486, 526, 381, 183, 51, 5, 590, 214, 160, 85, 60, 39, 3, 427, 203, }, { 589, 207, 89, 116, 40, 13, 3, 491, 1, 919, 919, 631, 631, 769, 633, 432, 308, 408, 378, 247, 94, 17, 1, 659, 247, 201, 105, 73, 51, 3, 466, 242, }, { 727, 266, 115, 151, 49, 17, 6, 439, 1, 977, 977, 642, 642, 718, 572, 379, 243, 285, 251, 133, 40, 1, 1, 756, 287, 253, 126, 94, 66, 4, 492, 280, }, { 940, 392, 180, 247, 82, 30, 14, 343, 1, 1064, 1064, 615, 616, 596, 414, 235, 146, 149, 108, 41, 1, 1, 1, 882, 314, 346, 172, 125, 83, 6, 489, 291, }, /* AC Inter bias group 1 tables */ { 440, 102, 33, 23, 2, 1, 1, 465, 85, 852, 852, 744, 743, 701, 496, 297, 193, 225, 200, 129, 58, 18, 2, 798, 450, 269, 202, 145, 308, 154, 646, 389, }, { 592, 151, 53, 43, 6, 1, 1, 409, 34, 875, 875, 748, 747, 723, 510, 305, 196, 229, 201, 130, 59, 18, 2, 800, 436, 253, 185, 115, 194, 88, 642, 368, }, { 759, 222, 86, 85, 17, 2, 1, 376, 46, 888, 888, 689, 688, 578, 408, 228, 143, 165, 141, 84, 35, 7, 1, 878, 488, 321, 244, 147, 266, 124, 612, 367, }, { 912, 298, 122, 133, 34, 7, 1, 261, 44, 1092, 1091, 496, 496, 409, 269, 150, 95, 106, 87, 49, 16, 1, 1, 1102, 602, 428, 335, 193, 323, 157, 423, 253, }, { 1072, 400, 180, 210, 60, 16, 3, 210, 40, 1063, 1063, 451, 451, 345, 221, 121, 73, 79, 64, 31, 6, 1, 1, 1105, 608, 462, 358, 202, 330, 155, 377, 228, }, { 1164, 503, 254, 330, 109, 34, 9, 167, 35, 1038, 1037, 390, 390, 278, 170, 89, 54, 56, 40, 13, 1, 1, 1, 1110, 607, 492, 401, 218, 343, 141, 323, 192, }, { 1173, 583, 321, 486, 196, 68, 23, 124, 23, 1037, 1037, 347, 346, 232, 139, 69, 40, 37, 20, 2, 1, 1, 1, 1128, 584, 506, 410, 199, 301, 113, 283, 159, }, { 1023, 591, 366, 699, 441, 228, 113, 79, 5, 1056, 1056, 291, 291, 173, 96, 38, 19, 8, 1, 1, 1, 1, 1, 1187, 527, 498, 409, 147, 210, 56, 263, 117, }, /* AC Intra bias group 2 tables */ { 311, 74, 27, 27, 5, 1, 1, 470, 24, 665, 667, 637, 638, 806, 687, 524, 402, 585, 679, 609, 364, 127, 20, 448, 210, 131, 76, 52, 111, 19, 393, 195, }, { 416, 104, 39, 38, 8, 1, 1, 545, 33, 730, 731, 692, 692, 866, 705, 501, 365, 495, 512, 387, 168, 39, 2, 517, 240, 154, 86, 64, 127, 19, 461, 247, }, { 474, 117, 43, 42, 9, 1, 1, 560, 40, 783, 783, 759, 760, 883, 698, 466, 318, 404, 377, 215, 66, 7, 1, 559, 259, 176, 110, 87, 170, 22, 520, 278, }, { 582, 149, 53, 53, 12, 2, 1, 473, 39, 992, 993, 712, 713, 792, 593, 373, 257, 299, 237, 114, 25, 1, 1, 710, 329, 221, 143, 116, 226, 26, 490, 259, }, { 744, 210, 78, 77, 16, 2, 1, 417, 37, 1034, 1035, 728, 728, 718, 509, 296, 175, 184, 122, 42, 3, 1, 1, 791, 363, 255, 168, 145, 311, 35, 492, 272, }, { 913, 291, 121, 128, 28, 4, 1, 334, 40, 1083, 1084, 711, 712, 624, 378, 191, 107, 95, 50, 7, 1, 1, 1, 876, 414, 288, 180, 164, 382, 39, 469, 275, }, { 1065, 405, 184, 216, 53, 8, 1, 236, 36, 1134, 1134, 685, 686, 465, 253, 113, 48, 41, 9, 1, 1, 1, 1, 965, 451, 309, 179, 166, 429, 53, 414, 249, }, { 1148, 548, 301, 438, 160, 42, 6, 84, 17, 1222, 1223, 574, 575, 272, 111, 23, 6, 2, 1, 1, 1, 1, 1, 1060, 502, 328, 159, 144, 501, 54, 302, 183, }, /* AC Inter bias group 2 tables */ { 403, 80, 24, 17, 1, 1, 1, 480, 90, 899, 899, 820, 819, 667, 413, 228, 133, 139, 98, 42, 10, 1, 1, 865, 470, 316, 222, 171, 419, 213, 645, 400, }, { 698, 169, 59, 49, 6, 1, 1, 414, 101, 894, 893, 761, 761, 561, 338, 171, 96, 97, 64, 26, 6, 1, 1, 896, 494, 343, 239, 192, 493, 215, 583, 366, }, { 914, 255, 94, 80, 10, 1, 1, 345, 128, 935, 935, 670, 671, 415, 222, 105, 55, 51, 30, 10, 1, 1, 1, 954, 530, 377, 274, 232, 641, 295, 456, 298, }, { 1103, 359, 146, 135, 20, 1, 1, 235, 119, 1042, 1042, 508, 507, 293, 146, 65, 33, 30, 16, 4, 1, 1, 1, 1031, 561, 407, 296, 265, 813, 317, 301, 192, }, { 1255, 504, 238, 265, 51, 5, 1, 185, 113, 1013, 1013, 437, 438, 212, 92, 41, 18, 15, 6, 1, 1, 1, 1, 976, 530, 386, 276, 260, 927, 357, 224, 148, }, { 1292, 610, 332, 460, 127, 16, 1, 136, 99, 1014, 1015, 384, 384, 153, 65, 25, 11, 6, 1, 1, 1, 1, 1, 942, 487, 343, 241, 238, 970, 358, 174, 103, }, { 1219, 655, 407, 700, 280, 55, 2, 100, 60, 1029, 1029, 337, 336, 119, 43, 11, 3, 2, 1, 1, 1, 1, 1, 894, 448, 305, 199, 213, 1005, 320, 136, 77, }, { 1099, 675, 435, 971, 581, 168, 12, 37, 16, 1181, 1081, 319, 318, 66, 11, 6, 1, 1, 1, 1, 1, 1, 1, 914, 370, 235, 138, 145, 949, 128, 94, 41, }, /* AC Intra bias group 3 tables */ { 486, 112, 39, 34, 6, 1, 1, 541, 67, 819, 818, 762, 763, 813, 643, 403, 280, 332, 295, 164, 53, 6, 1, 632, 294, 180, 131, 105, 208, 109, 594, 295, }, { 723, 191, 69, 65, 12, 1, 1, 445, 79, 865, 865, 816, 816, 750, 515, 290, 172, 184, 122, 46, 5, 1, 1, 740, 340, 213, 165, 129, 270, 168, 603, 326, }, { 884, 264, 102, 103, 21, 3, 1, 382, 68, 897, 897, 836, 836, 684, 427, 227, 119, 119, 70, 16, 1, 1, 1, 771, 367, 234, 184, 143, 272, 178, 555, 326, }, { 1028, 347, 153, 161, 36, 8, 1, 251, 44, 1083, 1084, 735, 735, 541, 289, 144, 77, 57, 23, 3, 1, 1, 1, 926, 422, 270, 215, 176, 301, 183, 443, 248, }, { 1155, 465, 224, 264, 71, 14, 3, 174, 27, 1110, 1111, 730, 731, 429, 206, 79, 30, 19, 4, 1, 1, 1, 1, 929, 443, 279, 225, 194, 298, 196, 354, 223, }, { 1191, 576, 296, 415, 144, 36, 8, 114, 16, 1162, 1162, 749, 749, 338, 108, 29, 8, 5, 1, 1, 1, 1, 1, 947, 458, 273, 207, 194, 248, 145, 258, 152, }, { 1169, 619, 366, 603, 247, 92, 23, 46, 1, 1236, 1236, 774, 775, 191, 35, 14, 1, 1, 1, 1, 1, 1, 1, 913, 449, 260, 214, 194, 180, 82, 174, 98, }, { 1006, 537, 381, 897, 504, 266, 101, 39, 1, 1307, 1307, 668, 667, 116, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1175, 261, 295, 70, 164, 107, 31, 10, 76, }, /* AC Inter bias group 3 tables */ { 652, 156, 53, 43, 5, 1, 1, 368, 128, 983, 984, 825, 825, 583, 331, 163, 88, 84, 48, 15, 1, 1, 1, 870, 480, 316, 228, 179, 421, 244, 562, 349, }, { 988, 280, 104, 87, 12, 1, 1, 282, 194, 980, 981, 738, 739, 395, 189, 80, 37, 31, 12, 2, 1, 1, 1, 862, 489, 333, 262, 214, 600, 446, 390, 260, }, { 1176, 399, 165, 154, 24, 2, 1, 218, 224, 1017, 1018, 651, 651, 280, 111, 42, 16, 9, 3, 1, 1, 1, 1, 787, 469, 324, 269, 229, 686, 603, 267, 194, }, { 1319, 530, 255, 268, 47, 4, 1, 113, 183, 1149, 1150, 461, 461, 173, 58, 17, 5, 3, 1, 1, 1, 1, 1, 768, 450, 305, 261, 221, 716, 835, 136, 97, }, { 1362, 669, 355, 465, 104, 9, 1, 76, 153, 1253, 1253, 398, 397, 102, 21, 5, 1, 1, 1, 1, 1, 1, 1, 596, 371, 238, 228, 196, 660, 954, 68, 53, }, { 1354, 741, 446, 702, 174, 15, 1, 38, 87, 1498, 1498, 294, 294, 43, 7, 1, 1, 1, 1, 1, 1, 1, 1, 381, 283, 165, 181, 155, 544, 1039, 25, 21, }, { 1262, 885, 546, 947, 263, 18, 1, 18, 27, 1908, 1908, 163, 162, 14, 1, 1, 1, 1, 1, 1, 1, 1, 1, 195, 152, 83, 125, 109, 361, 827, 7, 5, }, { 2539, 951, 369, 554, 212, 18, 1, 1, 1, 2290, 2289, 64, 64, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 18, 9, 55, 36, 184, 323, 1, 1, }, /* AC Intra bias group 4 tables */ { 921, 264, 101, 100, 19, 2, 1, 331, 98, 1015, 1016, 799, 799, 512, 269, 119, 60, 50, 17, 1, 1, 1, 1, 841, 442, 307, 222, 182, 493, 256, 438, 310, }, { 1147, 412, 184, 206, 50, 6, 1, 242, 141, 977, 976, 808, 807, 377, 135, 40, 10, 7, 1, 1, 1, 1, 1, 788, 402, 308, 223, 205, 584, 406, 316, 227, }, { 1243, 504, 238, 310, 79, 11, 1, 184, 150, 983, 984, 814, 813, 285, 56, 10, 1, 1, 1, 1, 1, 1, 1, 713, 377, 287, 217, 180, 615, 558, 208, 164, }, { 1266, 606, 329, 484, 161, 27, 1, 79, 92, 1187, 1188, 589, 588, 103, 10, 1, 1, 1, 1, 1, 1, 1, 1, 680, 371, 278, 221, 244, 614, 728, 80, 62, }, { 1126, 828, 435, 705, 443, 90, 8, 10, 55, 1220, 1219, 350, 350, 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 602, 330, 222, 168, 158, 612, 919, 104, 5, }, { 1210, 506, 1014, 926, 474, 240, 4, 1, 44, 1801, 1801, 171, 171, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 900, 132, 36, 11, 47, 191, 316, 2, 1, }, { 1210, 506, 1014, 926, 474, 240, 4, 1, 44, 1801, 1801, 171, 171, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 900, 132, 36, 11, 47, 191, 316, 2, 1, }, { 1210, 506, 1014, 926, 474, 240, 4, 1, 44, 1801, 1801, 171, 171, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 900, 132, 36, 11, 47, 191, 316, 2, 1, }, /* AC Inter bias group 4 tables */ { 1064, 325, 129, 117, 20, 2, 1, 266, 121, 1000, 1000, 706, 706, 348, 162, 67, 32, 25, 11, 1, 1, 1, 1, 876, 513, 363, 274, 225, 627, 384, 370, 251, }, { 1311, 517, 238, 254, 45, 3, 1, 188, 160, 1070, 1070, 635, 635, 239, 85, 30, 11, 6, 1, 1, 1, 1, 1, 744, 420, 313, 239, 206, 649, 541, 221, 155, }, { 1394, 632, 322, 385, 78, 7, 1, 134, 152, 1163, 1164, 607, 607, 185, 51, 12, 3, 1, 1, 1, 1, 1, 1, 631, 331, 275, 203, 182, 604, 620, 146, 98, }, { 1410, 727, 407, 546, 146, 19, 1, 67, 88, 1485, 1486, 419, 418, 103, 18, 3, 1, 1, 1, 1, 1, 1, 1, 555, 261, 234, 164, 148, 522, 654, 67, 39, }, { 1423, 822, 492, 719, 216, 22, 1, 28, 59, 1793, 1793, 323, 324, 37, 2, 1, 1, 1, 1, 1, 1, 1, 1, 376, 138, 158, 102, 119, 400, 604, 28, 9, }, { 1585, 923, 563, 918, 207, 25, 1, 5, 20, 2229, 2230, 172, 172, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 191, 40, 56, 22, 65, 243, 312, 2, 1, }, { 2225, 1100, 408, 608, 133, 8, 1, 1, 1, 2658, 2658, 25, 24, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 1, 1, 1, 1, 125, 16, 1, 1, }, { 2539, 951, 369, 554, 212, 18, 1, 1, 1, 2290, 2289, 64, 64, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 18, 9, 55, 36, 184, 323, 1, 1, }, }; } cortado-0.6.0/src/com/fluendo/jheora/Huffman.java100644 0 0 22717 11270111317 17022 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; import com.jcraft.jogg.*; public class Huffman { public static final int NUM_HUFF_TABLES = 80; public static final int DC_HUFF_OFFSET = 0; public static final int AC_HUFF_OFFSET = 16; public static final int AC_TABLE_2_THRESH = 5; public static final int AC_TABLE_3_THRESH = 14; public static final int AC_TABLE_4_THRESH = 27; public static final int DC_HUFF_CHOICES = 16; public static final int DC_HUFF_CHOICE_BITS = 4; public static final int AC_HUFF_CHOICES = 16; public static final int AC_HUFF_CHOICE_BITS = 4; /* Constants assosciated with entropy tokenisation. */ public static final int MAX_SINGLE_TOKEN_VALUE = 6; public static final int DCT_VAL_CAT2_MIN = 3; public static final int DCT_VAL_CAT3_MIN = 7; public static final int DCT_VAL_CAT4_MIN = 9; public static final int DCT_VAL_CAT5_MIN = 13; public static final int DCT_VAL_CAT6_MIN = 21; public static final int DCT_VAL_CAT7_MIN = 37; public static final int DCT_VAL_CAT8_MIN = 69; public static final int DCT_EOB_TOKEN = 0; public static final int DCT_EOB_PAIR_TOKEN = 1; public static final int DCT_EOB_TRIPLE_TOKEN = 2; public static final int DCT_REPEAT_RUN_TOKEN = 3; public static final int DCT_REPEAT_RUN2_TOKEN = 4; public static final int DCT_REPEAT_RUN3_TOKEN = 5; public static final int DCT_REPEAT_RUN4_TOKEN = 6; public static final int DCT_SHORT_ZRL_TOKEN = 7; public static final int DCT_ZRL_TOKEN = 8; public static final int ONE_TOKEN = 9; /* Special tokens for -1,1,-2,2 */ public static final int MINUS_ONE_TOKEN = 10; public static final int TWO_TOKEN = 11; public static final int MINUS_TWO_TOKEN = 12; public static final int LOW_VAL_TOKENS = (MINUS_TWO_TOKEN + 1); public static final int DCT_VAL_CATEGORY3 = (LOW_VAL_TOKENS + 4); public static final int DCT_VAL_CATEGORY4 = (DCT_VAL_CATEGORY3 + 1); public static final int DCT_VAL_CATEGORY5 = (DCT_VAL_CATEGORY4 + 1); public static final int DCT_VAL_CATEGORY6 = (DCT_VAL_CATEGORY5 + 1); public static final int DCT_VAL_CATEGORY7 = (DCT_VAL_CATEGORY6 + 1); public static final int DCT_VAL_CATEGORY8 = (DCT_VAL_CATEGORY7 + 1); public static final int DCT_RUN_CATEGORY1 = (DCT_VAL_CATEGORY8 + 1); public static final int DCT_RUN_CATEGORY1B = (DCT_RUN_CATEGORY1 + 5); public static final int DCT_RUN_CATEGORY1C = (DCT_RUN_CATEGORY1B + 1); public static final int DCT_RUN_CATEGORY2 = (DCT_RUN_CATEGORY1C + 1); /* 32 */ public static final int MAX_ENTROPY_TOKENS = (DCT_RUN_CATEGORY2 + 2); private static void createHuffmanList (HuffEntry[] huffRoot, int hIndex, short[] freqList) { HuffEntry entry_ptr; HuffEntry search_ptr; /* Create a HUFF entry for token zero. */ huffRoot[hIndex] = new HuffEntry(); huffRoot[hIndex].previous = null; huffRoot[hIndex].next = null; huffRoot[hIndex].Child[0] = null; huffRoot[hIndex].Child[1] = null; huffRoot[hIndex].value = 0; huffRoot[hIndex].frequency = freqList[0]; if ( huffRoot[hIndex].frequency == 0 ) huffRoot[hIndex].frequency = 1; /* Now add entries for all the other possible tokens. */ for (int i = 1; i < Huffman.MAX_ENTROPY_TOKENS; i++) { entry_ptr = new HuffEntry(); entry_ptr.value = i; entry_ptr.frequency = freqList[i]; entry_ptr.Child[0] = null; entry_ptr.Child[1] = null; /* Force min value of 1. This prevents the tree getting too deep. */ if ( entry_ptr.frequency == 0 ) entry_ptr.frequency = 1; if ( entry_ptr.frequency <= huffRoot[hIndex].frequency ){ entry_ptr.next = huffRoot[hIndex]; huffRoot[hIndex].previous = entry_ptr; entry_ptr.previous = null; huffRoot[hIndex] = entry_ptr; } else { search_ptr = huffRoot[hIndex]; while ( (search_ptr.next != null) && (search_ptr.frequency < entry_ptr.frequency) ){ search_ptr = search_ptr.next; } if ( search_ptr.frequency < entry_ptr.frequency ){ entry_ptr.next = null; entry_ptr.previous = search_ptr; search_ptr.next = entry_ptr; } else { entry_ptr.next = search_ptr; entry_ptr.previous = search_ptr.previous; search_ptr.previous.next = entry_ptr; search_ptr.previous = entry_ptr; } } } } private static void createCodeArray (HuffEntry huffRoot, int[] huffCodeArray, byte[] huffCodeLengthArray, int codeValue, byte codeLength) { /* If we are at a leaf then fill in a code array entry. */ if ((huffRoot.Child[0] == null) && (huffRoot.Child[1] == null)) { huffCodeArray[huffRoot.value] = codeValue; huffCodeLengthArray[huffRoot.value] = codeLength; } else { /* Recursive calls to scan down the tree. */ codeLength++; createCodeArray(huffRoot.Child[0], huffCodeArray, huffCodeLengthArray, ((codeValue << 1) + 0), codeLength); createCodeArray(huffRoot.Child[1], huffCodeArray, huffCodeLengthArray, ((codeValue << 1) + 1), codeLength); } } public static void buildHuffmanTree (HuffEntry[] huffRoot, int[] huffCodeArray, byte[] huffCodeLengthArray, int hIndex, short[] freqList ) { HuffEntry entry_ptr; HuffEntry search_ptr; /* First create a sorted linked list representing the frequencies of each token. */ createHuffmanList( huffRoot, hIndex, freqList ); /* Now build the tree from the list. */ /* While there are at least two items left in the list. */ while ( huffRoot[hIndex].next != null ){ /* Create the new node as the parent of the first two in the list. */ entry_ptr = new HuffEntry(); entry_ptr.value = -1; entry_ptr.frequency = huffRoot[hIndex].frequency + huffRoot[hIndex].next.frequency ; entry_ptr.Child[0] = huffRoot[hIndex]; entry_ptr.Child[1] = huffRoot[hIndex].next; /* If there are still more items in the list then insert the new node into the list. */ if (entry_ptr.Child[1].next != null ){ /* Set up the provisional 'new root' */ huffRoot[hIndex] = entry_ptr.Child[1].next; huffRoot[hIndex].previous = null; /* Now scan through the remaining list to insert the new entry at the appropriate point. */ if ( entry_ptr.frequency <= huffRoot[hIndex].frequency ){ entry_ptr.next = huffRoot[hIndex]; huffRoot[hIndex].previous = entry_ptr; entry_ptr.previous = null; huffRoot[hIndex] = entry_ptr; }else{ search_ptr = huffRoot[hIndex]; while ( (search_ptr.next != null) && (search_ptr.frequency < entry_ptr.frequency) ){ search_ptr = search_ptr.next; } if ( search_ptr.frequency < entry_ptr.frequency ){ entry_ptr.next = null; entry_ptr.previous = search_ptr; search_ptr.next = entry_ptr; }else{ entry_ptr.next = search_ptr; entry_ptr.previous = search_ptr.previous; search_ptr.previous.next = entry_ptr; search_ptr.previous = entry_ptr; } } }else{ /* Build has finished. */ entry_ptr.next = null; entry_ptr.previous = null; huffRoot[hIndex] = entry_ptr; } /* Delete the next/previous properties of the children (PROB NOT NEC). */ entry_ptr.Child[0].next = null; entry_ptr.Child[0].previous = null; entry_ptr.Child[1].next = null; entry_ptr.Child[1].previous = null; } /* Now build a code array from the tree. */ createCodeArray( huffRoot[hIndex], huffCodeArray, huffCodeLengthArray, 0, (byte)0); } public static int readHuffmanTrees(HuffEntry[] huffRoot, Buffer opb) { int i; for (i=0; i * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; import com.jcraft.jogg.*; public class Info { public int width; public int height; public int frame_width; public int frame_height; public int offset_x; public int offset_y; public int fps_numerator; public int fps_denominator; public int aspect_numerator; public int aspect_denominator; public Colorspace colorspace; public PixelFormat pixel_fmt; public int target_bitrate; public int quality; public int quick_p; /* quick encode/decode */ /* decode only */ public byte version_major; public byte version_minor; public byte version_subminor; public int keyframe_granule_shift; public long keyframe_frequency_force; /* codec_setup_info */ short[][][][] dequant_tables = new short[2][3][64][64]; int[] AcScaleFactorTable = new int[Constants.Q_TABLE_SIZE]; short[] DcScaleFactorTable = new short[Constants.Q_TABLE_SIZE]; int MaxQMatrixIndex; short[] qmats; HuffEntry[] HuffRoot = new HuffEntry[Huffman.NUM_HUFF_TABLES]; byte[] LoopFilterLimitValues = new byte[Constants.Q_TABLE_SIZE]; private static void _tp_readbuffer(Buffer opb, byte[] buf, int len) { for (int i=0; i Version.VERSION_MINOR) return Result.VERSION; width = (int)(opb.readB(16)<<4); height = (int)(opb.readB(16)<<4); frame_width = (int)opb.readB(24); frame_height = (int)opb.readB(24); offset_x = (int)opb.readB(8); offset_y = (int)opb.readB(8); /* Invert the offset so that it is from the top down */ offset_y = height-frame_height-offset_y; fps_numerator = opb.readB(32); fps_denominator = opb.readB(32); aspect_numerator = opb.readB(24); aspect_denominator = opb.readB(24); colorspace = Colorspace.spaces[opb.readB(8)]; target_bitrate = opb.readB(24); quality = opb.readB(6); keyframe_granule_shift = opb.readB(5); keyframe_frequency_force = 1< * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; public class JTheoraException extends Exception { private static final long serialVersionUID = 1L; private int error; public JTheoraException() { super(); } public JTheoraException(String str, int error) { super(str); this.error = error; } public int getErrorCode() { return error; } } cortado-0.6.0/src/com/fluendo/jheora/MotionVector.java100644 0 0 2275 11270111317 20043 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; public class MotionVector extends Coordinate { public static final MotionVector NULL = new MotionVector (0,0); public MotionVector () { super(); } public MotionVector (int x, int y) { super(x,y); } } cortado-0.6.0/src/com/fluendo/jheora/PixelFormat.java100644 0 0 2627 11336021765 17660 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; public class PixelFormat { public static final PixelFormat TH_PF_420 = new PixelFormat (); public static final PixelFormat TH_PF_RSVD = new PixelFormat(); public static final PixelFormat TH_PF_422 = new PixelFormat (); public static final PixelFormat TH_PF_444 = new PixelFormat (); public static final PixelFormat[] formats = { TH_PF_420, TH_PF_RSVD, TH_PF_422, TH_PF_444 }; private PixelFormat() { } } cortado-0.6.0/src/com/fluendo/jheora/Playback.java100644 0 0 21141 11336021765 17164 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; import com.jcraft.jogg.*; public class Playback { /* Different key frame types/methods */ private static final int DCT_KEY_FRAME = 0; //oggpack_buffer *opb; Buffer opb = new Buffer();; Info info; /* how far do we shift the granulepos to seperate out P frame counts? */ int keyframe_granule_shift; /***********************************************************************/ /* Decoder and Frame Type Information */ int DecoderErrorCode; int FramesHaveBeenSkipped; int PostProcessEnabled; int PostProcessingLevel; /* Perform post processing */ /* Frame Info */ byte FrameType; byte KeyFrameType; int QualitySetting; int FrameQIndex; /* Quality specified as a table index */ //int ThisFrameQualityValue; /* Quality value for this frame */ //int LastFrameQualityValue; /* Last Frame's Quality */ int CodedBlockIndex; /* Number of Coded Blocks */ int CodedBlocksThisFrame; /* Index into coded blocks */ int FrameSize; /* The number of bytes in the frame. */ int[] frameQIS = new int[3]; int frameNQIS; /* number of quality indices this frame uses */ /**********************************************************************/ /* Frame Size & Index Information */ int YPlaneSize; int UVPlaneSize; int YStride; int UVStride; int VFragments; int HFragments; int UnitFragments; int YPlaneFragments; int UVPlaneFragments; int UVShiftX; /* 1 unless Info.pixel_fmt == TH_PF_444 */ int UVShiftY; /* 0 unless Info.pixel_fmt == TH_PF_420 */ int ReconYPlaneSize; int ReconUVPlaneSize; int YDataOffset; int UDataOffset; int VDataOffset; int ReconYDataOffset; int ReconUDataOffset; int ReconVDataOffset; int YSuperBlocks; /* Number of SuperBlocks in a Y frame */ int UVSuperBlocks; /* Number of SuperBlocks in a U or V frame */ int SuperBlocks; /* Total number of SuperBlocks in a Y,U,V frame */ int YSBRows; /* Number of rows of SuperBlocks in a Y frame */ int YSBCols; /* Number of cols of SuperBlocks in a Y frame */ int UVSBRows; /* Number of rows of SuperBlocks in a U or V frame */ int UVSBCols; /* Number of cols of SuperBlocks in a U or V frame */ int YMacroBlocks; /* Number of Macro-Blocks in Y component */ int UVMacroBlocks; /* Number of Macro-Blocks in U/V component */ int MacroBlocks; /* Total number of Macro-Blocks */ /**********************************************************************/ /* Frames */ short[] ThisFrameRecon; short[] GoldenFrame; short[] LastFrameRecon; short[] PostProcessBuffer; /**********************************************************************/ /* Fragment Information */ int[] pixel_index_table; /* start address of first pixel of fragment in source */ int[] recon_pixel_index_table; /* start address of first pixel in recon buffer */ byte[] display_fragments; /* Fragment update map */ int[] CodedBlockList; /* A list of fragment indices for coded blocks. */ MotionVector[] FragMVect; /* fragment motion vectors */ int[] FragTokenCounts; /* Number of tokens per fragment */ int[] FragQIndex; /* Fragment Quality used in PostProcess */ byte[] FragCoefEOB; /* Position of last non 0 coef within QFragData */ short[][] QFragData; /* Fragment Coefficients Array Pointers */ byte[] FragQs; /* per block quantizers */ CodingMode[] FragCodingMethod; /* coding method for the fragment */ /***********************************************************************/ /* Macro Block and SuperBlock Information */ BlockMapping BlockMap; /* super block + sub macro block + sub frag -> FragIndex */ /* Coded flag arrays and counters for them */ byte[] SBCodedFlags; byte[] SBFullyFlags; byte[] MBCodedFlags; byte[] MBFullyFlags; /**********************************************************************/ Coordinate[] FragCoordinates; FrArray frArray = new FrArray(); Filter filter = new Filter(); /* quality index for each block */ byte[] blockQ; /* Dequantiser and rounding tables */ int[] quant_index = new int[64]; HuffEntry[] HuffRoot_VP3x = new HuffEntry[Huffman.NUM_HUFF_TABLES]; int[][] HuffCodeArray_VP3x; byte[][] HuffCodeLengthArray_VP3x; byte[] ExtraBitLengths_VP3x; public void clear() { if (opb != null) { opb = null; } } private static int ilog (long v) { int ret=0; while (v != 0) { ret++; v>>=1; } return ret; } public Playback (Info ci) { info = ci; DecoderErrorCode = 0; KeyFrameType = DCT_KEY_FRAME; FramesHaveBeenSkipped = 0; FrInit.InitFrameDetails(this); keyframe_granule_shift = ilog(ci.keyframe_frequency_force-1); //LastFrameQualityValue = 0; /* Initialise version specific quantiser and in-loop filter values */ filter.copyFilterTables(ci); /* Huffman setup */ initHuffmanTrees(ci); } public int getFrameType() { return FrameType; } void setFrameType(byte FrType ){ /* Set the appropriate frame type according to the request. */ switch ( FrType ){ case Constants.BASE_FRAME: FrameType = FrType; break; default: FrameType = FrType; break; } } public void clearHuffmanSet() { Huffman.clearHuffmanTrees(HuffRoot_VP3x); HuffCodeArray_VP3x = null; HuffCodeLengthArray_VP3x = null; } public void initHuffmanSet() { clearHuffmanSet(); ExtraBitLengths_VP3x = HuffTables.ExtraBitLengths_VP31; HuffCodeArray_VP3x = new int[Huffman.NUM_HUFF_TABLES][Huffman.MAX_ENTROPY_TOKENS]; HuffCodeLengthArray_VP3x = new byte[Huffman.NUM_HUFF_TABLES][Huffman.MAX_ENTROPY_TOKENS]; for (int i = 0; i < Huffman.NUM_HUFF_TABLES; i++ ){ Huffman.buildHuffmanTree(HuffRoot_VP3x, HuffCodeArray_VP3x[i], HuffCodeLengthArray_VP3x[i], i, HuffTables.FrequencyCounts_VP3[i]); } } public int readHuffmanTrees(Info ci, Buffer opb) { int i; for (i=0; i * 2008 Maik Merten * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; import com.jcraft.jogg.*; public class Quant { private static int ilog (long v) { int ret=0; while (v != 0) { ret++; v>>=1; } return ret; } public static int readQTables(Info ci, Buffer opb) { /* Variable names according to Theora spec where it makes sense. * I *know* this may violate Java coding style rules, but I consider * readability against the Theora spec to be more important */ long NBITS,value; int x, bmi, NBMS; /* A 2 × 3 array containing the number of quant ranges for a given qti and pli , respectively. This is at most 63. */ int[][] NQRS = new int[2][3]; /* A 2 × 3 × 63 array of the sizes of each quant range for a given qti and pli , respectively. Only the first NQRS[qti ][pli ] values are used. */ int[][][] QRSIZES = new int[2][3][63]; /* A 2 × 3 × 64 array of the bmi ’s used for each quant range for a given qti and pli, respectively. Only the first (NQRS[qti ][pli ] + 1) values are used. */ int[][][] QRBMIS = new int[2][3][64]; int qri, qi, qtj, plj; /* 1. Read a 4-bit unsigned integer. Assign NBITS the value read, plus one. */ NBITS = opb.readB(4); NBITS++; /* 2. For each consecutive value of qi from 0 to 63, inclusive: (a) Read an NBITS-bit unsigned integer as ACSCALE[qi ]. */ for(x=0; x < 64; x++) { value = opb.readB((int)NBITS); if(NBITS<0) return Result.BADHEADER; ci.AcScaleFactorTable[x]=(int)value; } /* 3. Read a 4-bit unsigned integer. Assign NBITS the value read, plus one. */ NBITS = opb.readB(4); NBITS++; /* 4. For each consecutive value of qi from 0 to 63, inclusive: (a) Read an NBITS-bit unsigned integer as DCSCALE[qi ]. */ for(x=0; x 384) { return Result.BADHEADER; } ci.MaxQMatrixIndex = NBMS; /* 6. For each consecutive value of bmi from 0 to (NBMS - 1), inclusive: (a) For each consecutive value of ci from 0 to 63, inclusive: i. Read an 8-bit unsigned integer as BMS[bmi ][ci ]. */ ci.qmats= new short[NBMS*64]; for(bmi=0; bmi 0 || pli > 0) { /* i. If qti > 0 or pli > 0, read a 1-bit unsigned integer as NEWQR. */ NEWQR = opb.readB(1); } else { /* ii. Else, assign NEWQR the value one. */ NEWQR = 1; } if(NEWQR == 0) { /* If NEWQR is zero, then we are copying a previously defined set of quant ranges. In that case: */ int RPQR; if(qti > 0) { /* A. If qti > 0, read a 1-bit unsigned integer as RPQR. */ RPQR = opb.readB(1); } else { /* B. Else, assign RPQR the value zero. */ RPQR = 0; } if(RPQR == 1) { /* C. If RPQR is one, assign qtj the value (qti - 1) and assign plj the value pli . This selects the set of quant ranges defined for the same color plane as this one, but for the previous quantization type. */ qtj = qti - 1; plj = pli; } else { /* D. Else assign qtj the value (3 * qti + pli - 1)//3 and assign plj the value (pli + 2)%3. This selects the most recent set of quant ranges defined. */ qtj = (3 * qti + pli - 1) / 3; plj = (pli + 2) % 3; } /* E. Assign NQRS[qti ][pli ] the value NQRS[qtj ][plj ]. */ NQRS[qti][pli] = NQRS[qtj][plj]; /* F. Assign QRSIZES[qti ][pli ] the values in QRSIZES[qtj ][plj ]. */ QRSIZES[qti][pli] = QRSIZES[qtj][plj]; /* G. Assign QRBMIS[qti ][pli ] the values in QRBMIS[qtj ][plj ]. */ QRBMIS[qti][pli] = QRBMIS[qtj][plj]; } else { /* Else, NEWQR is one, which indicates that we are defining a new set of quant ranges. In that case: */ /*A. Assign qri the value zero. */ qri = 0; /*B. Assign qi the value zero. */ qi = 0; /* C. Read an ilog(NBMS - 1)-bit unsigned integer as QRBMIS[qti ][pli ][qri ]. If this is greater than or equal to NBMS, stop. The stream is undecodable. */ QRBMIS[qti][pli][qri] = opb.readB(ilog(NBMS - 1)); if(QRBMIS[qti][pli][qri] >= NBMS) { System.out.println("bad header (1)"); return Result.BADHEADER; } do { /* D. Read an ilog(62 - qi )-bit unsigned integer. Assign QRSIZES[qti ][pli ][qri ] the value read, plus one. */ QRSIZES[qti][pli][qri] = opb.readB(ilog(62 - qi)) + 1; /* E. Assign qi the value qi + QRSIZES[qti ][pli ][qri ]. */ qi = qi + QRSIZES[qti][pli][qri]; /* F. Assign qri the value qri + 1. */ qri = qri + 1; /* G. Read an ilog(NBMS - 1)-bit unsigned integer as QRBMIS[qti ][pli ][qri ]. */ QRBMIS[qti][pli][qri] = opb.readB(ilog(NBMS - 1)); /* H. If qi is less than 63, go back to step 7(a)ivD. */ } while(qi < 63); /* I. If qi is greater than 63, stop. The stream is undecodable. */ if(qi > 63) { System.out.println("bad header (2): " + qi); return Result.BADHEADER; } /* J. Assign NQRS[qti ][pli ] the value qri . */ NQRS[qti][pli] = qri; } } } /* Compute all 384 matrices */ for(int coding = 0; coding < 2; ++coding) { for(int plane = 0; plane < 3; ++plane) { for(int quality = 0; quality < 64; ++quality) { short[] scaledmat = compQuantMatrix(ci.AcScaleFactorTable, ci.DcScaleFactorTable, ci.qmats, NQRS, QRSIZES, QRBMIS, coding, plane, quality); for(int coeff = 0; coeff < 64; ++coeff) { int j = Constants.dequant_index[coeff]; ci.dequant_tables[coding][plane][quality][coeff] = scaledmat[j]; } } } } return 0; } static short[] compQuantMatrix(int[] ACSCALE, short[] DCSCALE, short[] BMS, int[][] NQRS, int[][][] QRSIZES, int[][][] QRBMIS, int qti, int pli, int qi) { /* Variable names according to Theora spec where it makes sense. * I *know* this may violate Java coding style rules, but I consider * readability against the Theora spec to be more important */ short[] QMAT = new short[64]; int qri, qrj; /* 1. Assign qri the index of a quant range such that \qi \ge \sum_{\qrj=0}^{\qri-1} QRSIZES[\qti][\pli][\qrj], and \qi \le \sum_{\qrj=0}^{\qri} QRSIZES[\qti][\pli][\qrj], */ for(qri = 0; qri < 63; ++qri) { int sum1 = 0; for(qrj = 0; qrj < qri; ++qrj) { sum1 += QRSIZES[qti][pli][qrj]; } int sum2 = 0; for(qrj = 0; qrj <= qri; ++qrj) { sum2 += QRSIZES[qti][pli][qrj]; } if(qi >= sum1 && qi <= sum2) break; } /* 2. Assign QISTART the value \sum_{\qrj=0}^{\qri-1} QRSIZES[\qti][\pli][\qrj]. */ int QISTART = 0; for(qrj = 0; qrj < qri; ++qrj) { QISTART += QRSIZES[qti][pli][qrj]; } /* 3. Assign QIEND the value \sum_{\qrj=0}^{\qri} QRSIZES[\qti][\pli][\qrj]. */ int QIEND = 0; for(qrj = 0; qrj <= qri; ++qrj) { QIEND += QRSIZES[qti][pli][qrj]; } /* 4. Assign bmi the value QRBMIS[qti ][pli ][qri ]. */ int bmi = QRBMIS[qti][pli][qri]; /* 5. Assign bmj the value QRBMIS[qti ][pli ][qri + 1]. */ int bmj = QRBMIS[qti][pli][qri + 1]; int[] BM = new int[64]; int QMIN; /* 6. For each consecutive value of ci from 0 to 63, inclusive: */ for(int ci = 0; ci < 64; ++ci) { /* (a) Assign BM[ci ] the value (2 ∗ (QIEND − qi ) ∗ BMS[bmi ][ci ] + 2 ∗ (qi − QISTART) ∗ BMS[bmj ][ci ] + QRSIZES[qti ][pli ][qri ])//(2 ∗ QRSIZES[qti ][pli ][qri ]) */ BM[ci] = (2 * (QIEND - qi) * BMS[(bmi<<6) + ci] + 2 * (qi - QISTART) * BMS[(bmj<<6) + ci] + QRSIZES[qti][pli][qri]) / (2 * QRSIZES[qti][pli][qri]); /* (b) Assign QMIN the value given by Table 6.18 according to qti and ci . */ if(ci == 0 && qti == 0) QMIN = 16; else if(ci > 0 && qti == 0) QMIN = 8; else if(ci == 0 && qti == 1) QMIN = 32; else QMIN = 16; int QSCALE; if(ci == 0) { /* (c) If ci equals zero, assign QSCALE the value DCSCALE[qi ]. */ QSCALE = DCSCALE[qi]; } else { /* (d) Else, assign QSCALE the value ACSCALE[qi ]. */ QSCALE = ACSCALE[qi]; } /*(e) Assign QMAT[ci ] the value max(QMIN, min((QSCALE ∗ BM[ci ]//100) ∗ 4, 4096)). */ QMAT[ci] = (short)Math.max(QMIN, Math.min((QSCALE * BM[ci]/100) * 4,4096)); } return QMAT; } }cortado-0.6.0/src/com/fluendo/jheora/Recon.java100644 0 0 10603 11335050154 16476 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; public final class Recon { private static final short clamp255(int val) { return (short)((~(val>>31)) & 255 & (val | ((255-val)>>31))); } public static final void CopyBlock(short[] src, short[] dest, int idx, int srcstride) { int i, off=idx; for (i=0; i<8; i++){ dest[off+0] = src[off+0]; dest[off+1] = src[off+1]; dest[off+2] = src[off+2]; dest[off+3] = src[off+3]; dest[off+4] = src[off+4]; dest[off+5] = src[off+5]; dest[off+6] = src[off+6]; dest[off+7] = src[off+7]; off+=srcstride; } } public static final void ReconIntra(short[] ReconPtr, int idx, short[] ChangePtr, int LineStep) { int i, roff=idx, coff=0; for (i=0; i<8; i++ ){ /* Convert the data back to 8 bit unsigned */ /* Saturate the output to unsigned 8 bit values */ ReconPtr[roff+0] = clamp255(ChangePtr[coff++] + 128); ReconPtr[roff+1] = clamp255(ChangePtr[coff++] + 128); ReconPtr[roff+2] = clamp255(ChangePtr[coff++] + 128); ReconPtr[roff+3] = clamp255(ChangePtr[coff++] + 128); ReconPtr[roff+4] = clamp255(ChangePtr[coff++] + 128); ReconPtr[roff+5] = clamp255(ChangePtr[coff++] + 128); ReconPtr[roff+6] = clamp255(ChangePtr[coff++] + 128); ReconPtr[roff+7] = clamp255(ChangePtr[coff++] + 128); roff += LineStep; } } public static final void ReconInter(short[] ReconPtr, int idx1, short[] RefPtr, int idx2, short[] ChangePtr, int LineStep ) { int coff=0, roff1=idx1, roff2=idx2, i; for (i = 0; i < 8; i++) { ReconPtr[roff1+0] = clamp255(RefPtr[roff2+0] + ChangePtr[coff++]); ReconPtr[roff1+1] = clamp255(RefPtr[roff2+1] + ChangePtr[coff++]); ReconPtr[roff1+2] = clamp255(RefPtr[roff2+2] + ChangePtr[coff++]); ReconPtr[roff1+3] = clamp255(RefPtr[roff2+3] + ChangePtr[coff++]); ReconPtr[roff1+4] = clamp255(RefPtr[roff2+4] + ChangePtr[coff++]); ReconPtr[roff1+5] = clamp255(RefPtr[roff2+5] + ChangePtr[coff++]); ReconPtr[roff1+6] = clamp255(RefPtr[roff2+6] + ChangePtr[coff++]); ReconPtr[roff1+7] = clamp255(RefPtr[roff2+7] + ChangePtr[coff++]); roff1 += LineStep; roff2 += LineStep; } } public static final void ReconInterHalfPixel2(short[] ReconPtr, int idx1, short[] RefPtr1, int idx2, short[] RefPtr2, int idx3, short[] ChangePtr, int LineStep ) { int coff=0, roff1=idx1, roff2=idx2, roff3=idx3, i; for (i = 0; i < 8; i++ ){ ReconPtr[roff1+0] = clamp255(((RefPtr1[roff2+0] + RefPtr2[roff3+0]) >> 1) + ChangePtr[coff++]); ReconPtr[roff1+1] = clamp255(((RefPtr1[roff2+1] + RefPtr2[roff3+1]) >> 1) + ChangePtr[coff++]); ReconPtr[roff1+2] = clamp255(((RefPtr1[roff2+2] + RefPtr2[roff3+2]) >> 1) + ChangePtr[coff++]); ReconPtr[roff1+3] = clamp255(((RefPtr1[roff2+3] + RefPtr2[roff3+3]) >> 1) + ChangePtr[coff++]); ReconPtr[roff1+4] = clamp255(((RefPtr1[roff2+4] + RefPtr2[roff3+4]) >> 1) + ChangePtr[coff++]); ReconPtr[roff1+5] = clamp255(((RefPtr1[roff2+5] + RefPtr2[roff3+5]) >> 1) + ChangePtr[coff++]); ReconPtr[roff1+6] = clamp255(((RefPtr1[roff2+6] + RefPtr2[roff3+6]) >> 1) + ChangePtr[coff++]); ReconPtr[roff1+7] = clamp255(((RefPtr1[roff2+7] + RefPtr2[roff3+7]) >> 1) + ChangePtr[coff++]); roff1 += LineStep; roff2 += LineStep; roff3 += LineStep; } } } cortado-0.6.0/src/com/fluendo/jheora/Result.java100644 0 0 2526 11270111317 16670 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; public final class Result { public static final int FAULT = -1; public static final int EINVAL = -10; public static final int BADHEADER = -20; public static final int NOTFORMAT = -21; public static final int VERSION = -22; public static final int IMPL = -23; public static final int BADPACKET = -24; public static final int NEWPACKET = -25; } cortado-0.6.0/src/com/fluendo/jheora/State.java100644 0 0 10007 11350725171 16513 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; import com.jcraft.jogg.*; public class State { long granulepos; private Playback pbi; private Decode dec; public void clear() { if(pbi != null){ pbi.info.clear(); pbi.clearHuffmanSet(); FrInit.ClearFragmentInfo(pbi); FrInit.ClearFrameInfo(pbi); pbi.clear(); } pbi = null; } public int decodeInit(Info ci) { pbi = new Playback(ci); dec = new Decode(pbi); granulepos=-1; return(0); } public boolean isKeyframe (Packet op) { return (op.packet_base[op.packet] & 0x40) == 0; } public int decodePacketin (Packet op) { long ret; pbi.DecoderErrorCode = 0; if (op.bytes>0) { pbi.opb.readinit(op.packet_base, op.packet, op.bytes); /* verify that this is a video frame */ ret = pbi.opb.readB(1); if (ret==0) { try { ret=dec.loadAndDecode(); } catch(Exception e) { /* If lock onto the bitstream is lost all sort of Exceptions can occur. * The bitstream damage may be local, so the next packet may be okay. */ e.printStackTrace(); return Result.BADPACKET; } if(ret != 0) return (int) ret; } else { return Result.BADPACKET; } } if(op.granulepos>-1) granulepos=op.granulepos; else{ if(granulepos==-1){ granulepos=0; } else { if ((op.bytes>0) && (pbi.FrameType == Constants.BASE_FRAME)){ long frames= granulepos & ((1<>=pbi.keyframe_granule_shift; granulepos+=frames+1; granulepos<<=pbi.keyframe_granule_shift; }else granulepos++; } } return(0); } public int decodeYUVout (YUVBuffer yuv) { yuv.y_width = pbi.info.width; yuv.y_height = pbi.info.height; yuv.y_stride = pbi.YStride; yuv.uv_width = pbi.info.width >> pbi.UVShiftX; yuv.uv_height = pbi.info.height >> pbi.UVShiftY; yuv.uv_stride = pbi.UVStride; if(pbi.PostProcessingLevel != 0){ yuv.data = pbi.PostProcessBuffer; }else{ yuv.data = pbi.LastFrameRecon; } yuv.y_offset = pbi.ReconYDataOffset; yuv.u_offset = pbi.ReconUDataOffset; yuv.v_offset = pbi.ReconVDataOffset; /* we must flip the internal representation, so make the stride negative and start at the end */ yuv.y_offset += yuv.y_stride * (yuv.y_height - 1); yuv.u_offset += yuv.uv_stride * (yuv.uv_height - 1); yuv.v_offset += yuv.uv_stride * (yuv.uv_height - 1); yuv.y_stride = - yuv.y_stride; yuv.uv_stride = - yuv.uv_stride; yuv.newPixels(); return 0; } /* returns, in seconds, absolute time of current packet in given logical stream */ public double granuleTime(long granulepos) { if(granulepos>=0){ long iframe=granulepos>>pbi.keyframe_granule_shift; long pframe=granulepos-(iframe< * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; public class Version { public static final int VERSION_MAJOR = 3; public static final int VERSION_MINOR = 2; public static final int VERSION_SUB = 0; private static final String VENDOR_STRING = "Xiph.Org libTheora I 20040317 3 2 0"; public static String getVersionString() { return VENDOR_STRING; } public static int getVersionNumber() { return (VERSION_MAJOR<<16) + (VERSION_MINOR<<8) + (VERSION_SUB); } } cortado-0.6.0/src/com/fluendo/jheora/YUVBuffer.java100644 0 0 25447 11336021765 17270 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; import java.awt.image.*; //import java.util.Random; public class YUVBuffer implements ImageProducer { public int y_width; public int y_height; public int y_stride; public int uv_width; public int uv_height; public int uv_stride; public short[] data; public int y_offset; public int u_offset; public int v_offset; private int[] pixels; private int pix_size; private boolean newPixels = true; private ColorModel colorModel = ColorModel.getRGBdefault(); private ImageProducer filteredThis; private int crop_x; private int crop_y; private int crop_w; private int crop_h; public void addConsumer(ImageConsumer ic) { } public boolean isConsumer(ImageConsumer ic) { return false; } public void removeConsumer(ImageConsumer ic) { } public void requestTopDownLeftRightResend(ImageConsumer ic) { } public void startProduction(ImageConsumer ic) { ic.setColorModel(colorModel); ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT | ImageConsumer.COMPLETESCANLINES | ImageConsumer.SINGLEFRAME | ImageConsumer.SINGLEPASS); ic.setDimensions(y_width, y_height); prepareRGBData(0, 0, y_width, y_height); ic.setPixels(0, 0, y_width, y_height, colorModel, pixels, 0, y_width); ic.imageComplete(ImageConsumer.STATICIMAGEDONE); } private synchronized void prepareRGBData(int x, int y, int width, int height) { if (!newPixels) { return; } int size = width * height; try { if (size != pix_size) { pixels = new int[size]; pix_size = size; } /* rely on the buffer size being set correctly, and the only allowed video formats being Theora's video formats */ if (uv_height < y_height) YUV420toRGB(x, y, width, height); else if (uv_width == y_width) YUV444toRGB(x, y, width, height); else YUV422toRGB(x, y, width, height); } catch (Throwable t) { /* ignore */ } newPixels = false; } public synchronized void newPixels() { newPixels = true; } // cropping code provided by Benjamin Schwartz public Object getObject(int x, int y, int width, int height) { if (x == 0 && y == 0 && width == y_width && height == y_height) { return this; } else { if (x != crop_x || y != crop_y || width != crop_w || height != crop_h) { crop_x = x; crop_y = y; crop_w = width; crop_h = height; CropImageFilter cropFilter = new CropImageFilter(crop_x, crop_y, crop_w, crop_h); filteredThis = new FilteredImageSource(this, cropFilter); } return filteredThis; } } private void YUV420toRGB(int x, int y, int width, int height) { /* * this modified version of the original YUVtoRGB was * provided by Ilan and Yaniv Ben Hagai. * * additional thanks to Gumboot for helping with making this * code perform better. */ // Set up starting values for YUV pointers int YPtr = y_offset + x + y * (y_stride); int YPtr2 = YPtr + y_stride; int UPtr = u_offset + x / 2 + (y / 2) * (uv_stride); int VPtr = v_offset + x / 2 + (y / 2) * (uv_stride); int RGBPtr = 0; int RGBPtr2 = width; int width2 = width / 2; int height2 = height / 2; // Set the line step for the Y and UV planes and YPtr2 int YStep = y_stride * 2 - (width2) * 2; int UVStep = uv_stride - (width2); int RGBStep = width; for (int i = 0; i < height2; i++) { for (int j = 0; j < width2; j++) { int D, E, r, g, b, t1, t2, t3, t4; D = data[UPtr++]; E = data[VPtr++]; t1 = 298 * (data[YPtr] - 16); t2 = 409 * E - 409*128 + 128; t3 = (100 * D) + (208 * E) - 100*128 - 208*128 - 128; t4 = 516 * D - 516*128 + 128; r = (t1 + t2); g = (t1 - t3); b = (t1 + t4); // retrieve data for next pixel now, hide latency? t1 = 298 * (data[YPtr + 1] - 16); // pack pixel pixels[RGBPtr] = (clamp65280(r) << 8) | clamp65280(g) | (clamp65280(b)>>8) | 0xff000000; r = (t1 + t2); g = (t1 - t3); b = (t1 + t4); // retrieve data for next pixel now, hide latency? t1 = 298 * (data[YPtr2] - 16); // pack pixel pixels[RGBPtr + 1] = (clamp65280(r) << 8) | clamp65280(g) | (clamp65280(b)>>8) | 0xff000000; r = (t1 + t2); g = (t1 - t3); b = (t1 + t4); // retrieve data for next pixel now, hide latency? t1 = 298 * (data[YPtr2 + 1] - 16); // pack pixel pixels[RGBPtr2] = (clamp65280(r) << 8) | clamp65280(g) | (clamp65280(b)>>8) | 0xff000000; r = (t1 + t2); g = (t1 - t3); b = (t1 + t4); // pack pixel pixels[RGBPtr2 + 1] = (clamp65280(r) << 8) | clamp65280(g) | (clamp65280(b)>>8) | 0xff000000; YPtr += 2; YPtr2 += 2; RGBPtr += 2; RGBPtr2 += 2; } // Increment the various pointers YPtr += YStep; YPtr2 += YStep; UPtr += UVStep; VPtr += UVStep; RGBPtr += RGBStep; RGBPtr2 += RGBStep; } } // kept for reference /*private static final int clamp255(int val) { return ((~(val>>31)) & 255 & (val | ((255-val)>>31))); }*/ private static final int clamp65280(int val) { /* 65280 == 255 << 8 == 0x0000FF00 */ /* This function is just like clamp255, but only acting on the top 24 bits (bottom 8 are zero'd). This allows val, initially scaled to 65536, to be clamped without shifting, thereby saving one shift. (RGB packing must be aware that the info is in the second-lowest byte.) */ return ((~(val>>31)) & 65280 & (val | ((65280-val)>>31))); } private void YUV444toRGB(int x, int y, int width, int height) { for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { int D, E, r, g, b, t1, t2, t3, t4, p; p = x + i + (j + y)*y_stride; D = data[u_offset + p]; E = data[v_offset + p]; t1 = 298 * (data[y_offset + p] - 16); t2 = 409 * E - 409*128 + 128; t3 = (100 * D) + (208 * E) - 100*128 - 208*128 - 128; t4 = 516 * D - 516*128 + 128; r = (t1 + t2); g = (t1 - t3); b = (t1 + t4); // pack pixel pixels[i + j*width] = (clamp65280(r) << 8) | clamp65280(g) | (clamp65280(b)>>8) | 0xff000000; } } } private void YUV422toRGB(int x, int y, int width, int height) { int x2 = x/2; int width2 = width/2; for (int j = 0; j < height; j++) { for (int i = 0; i < width2; i++) { int D, E, r, g, b, t1, t2, t3, t4, p; p = x2 + i + (y + j)*uv_stride; D = data[u_offset + p]; E = data[v_offset + p]; p = y_offset + 2*(x2 + i) + (y + j)*y_stride; t1 = 298 * (data[p] - 16); t2 = 409 * E - 409*128 + 128; t3 = (100 * D) + (208 * E) - 100*128 - 208*128 - 128; t4 = 516 * D - 516*128 + 128; r = (t1 + t2); g = (t1 - t3); b = (t1 + t4); p++; t1 = 298 * (data[p] - 16); // pack pixel p = 2*i + j*width; pixels[p] = (clamp65280(r) << 8) | clamp65280(g) | (clamp65280(b)>>8) | 0xff000000; r = (t1 + t2); g = (t1 - t3); b = (t1 + t4); p++; // pack pixel pixels[p] = (clamp65280(r) << 8) | clamp65280(g) | (clamp65280(b)>>8) | 0xff000000; } } } // some benchmarking stuff, uncomment if you need it /*public static void main(String[] args) { YUVBuffer yuvbuf = new YUVBuffer(); // let's create a 1280x720 picture with noise int x = 1280; int y = 720; int size = (x * y) + (x * y) / 2; short[] picdata = new short[size]; Random r = new Random(); for (int i = 0; i < picdata.length; ++i) { picdata[i] = (short) (r.nextInt(255) | 0xFF); } System.out.println("bench..."); yuvbuf.data = picdata; yuvbuf.y_height = y; yuvbuf.y_width = x; yuvbuf.y_stride = x; yuvbuf.uv_height = y / 2; yuvbuf.uv_width = x / 2; yuvbuf.uv_stride = x / 2; yuvbuf.u_offset = x / 2; yuvbuf.v_offset = x + x / 2; int times = 5000; long start = System.currentTimeMillis(); for (int i = 0; i < times; ++i) { yuvbuf.newPixels(); yuvbuf.prepareRGBData(0, 0, x, y); } long end = System.currentTimeMillis(); System.out.println("average conversion time per frame: " + ((double) (end - start)) / (times * 1f) + " ms."); }*/ } cortado-0.6.0/src/com/fluendo/jheora/iDCT.java100644 0 0 25206 11270111317 16215 0ustar 0 0 /* Jheora * Copyright (C) 2004 Fluendo S.L. * * Written by: 2004 Wim Taymans * * Many thanks to * The Xiph.Org Foundation http://www.xiph.org/ * Jheora was based on their Theora reference decoder. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jheora; public final class iDCT { private static final int IdctAdjustBeforeShift = 8; private static final int xC1S7 = 64277; private static final int xC2S6 = 60547; private static final int xC3S5 = 54491; private static final int xC4S4 = 46341; private static final int xC5S3 = 36410; private static final int xC6S2 = 25080; private static final int xC7S1 = 12785; private int[] ip = new int[64]; private final void dequant_slow(short[] dequant_coeffs, short[] quantized_list, int[] DCT_block) { for(int i = 0; i < 64; i++) { DCT_block[Constants.dequant_index[i]] = quantized_list[i] * dequant_coeffs[i]; /* if (i%8 ==0) System.out.print(": "); System.out.print("("+DCT_block[Constants.dequant_index[i]]+" "); System.out.print(dequant_coeffs[i]+" "); System.out.print(quantized_list[i]+")"); if (i%8 ==7) System.out.print("\n"); */ } } public final void IDctSlow (short[] InputData, short[]QuantMatrix, short[] OutputData) { short[] op = OutputData; int _A, _B, _C, _D, _Ad, _Bd, _Cd, _Dd, _E, _F, _G, _H; int _Ed, _Gd, _Add, _Bdd, _Fd, _Hd; int t1, t2; dequant_slow (QuantMatrix, InputData, ip); /* Inverse DCT on the rows now */ for (int loop = 0, off=0; loop < 8; loop++, off+=8){ /* Check for non-zero values */ if ((ip[0 + off] | ip[1 + off] | ip[2 + off] | ip[3 + off] | ip[4 + off] | ip[5 + off] | ip[6 + off] | ip[7 + off]) != 0 ) { t1 = (xC1S7 * ip[1 + off]) >> 16; t2 = (xC7S1 * ip[7 + off]) >> 16; _A = t1 + t2; t1 = (xC7S1 * ip[1 + off]) >> 16; t2 = (xC1S7 * ip[7 + off]) >> 16; _B = t1 - t2; t1 = (xC3S5 * ip[3 + off]) >> 16; t2 = (xC5S3 * ip[5 + off]) >> 16; _C = t1 + t2; t1 = (xC3S5 * ip[5 + off]) >> 16; t2 = (xC5S3 * ip[3 + off]) >> 16; _D = t1 - t2; _Ad = (xC4S4 * (short)(_A - _C)) >> 16; _Bd = (xC4S4 * (short)(_B - _D)) >> 16; _Cd = _A + _C; _Dd = _B + _D; _E = (xC4S4 * (short)(ip[0 + off] + ip[4 + off])) >> 16; _F = (xC4S4 * (short)(ip[0 + off] - ip[4 + off])) >> 16; t1 = (xC2S6 * ip[2 + off]) >> 16; t2 = (xC6S2 * ip[6 + off]) >> 16; _G = t1 + t2; t1 = (xC6S2 * ip[2 + off]) >> 16; t2 = (xC2S6 * ip[6 + off]) >> 16; _H = t1 - t2; _Ed = _E - _G; _Gd = _E + _G; _Add = _F + _Ad; _Bdd = _Bd - _H; _Fd = _F - _Ad; _Hd = _Bd + _H; /* Final sequence of operations over-write original inputs. */ ip[0 + off] = (short)((_Gd + _Cd ) >> 0); ip[7 + off] = (short)((_Gd - _Cd ) >> 0); ip[1 + off] = (short)((_Add + _Hd ) >> 0); ip[2 + off] = (short)((_Add - _Hd ) >> 0); ip[3 + off] = (short)((_Ed + _Dd ) >> 0); ip[4 + off] = (short)((_Ed - _Dd ) >> 0); ip[5 + off] = (short)((_Fd + _Bdd ) >> 0); ip[6 + off] = (short)((_Fd - _Bdd ) >> 0); } } for (int loop = 0, off=0; loop < 8; loop++, off++){ /* Check for non-zero values (bitwise or faster than ||) */ if ((ip[0 * 8 + off] | ip[1 * 8 + off] | ip[2 * 8 + off] | ip[3 * 8 + off] | ip[4 * 8 + off] | ip[5 * 8 + off] | ip[6 * 8 + off] | ip[7 * 8 + off]) != 0) { t1 = (xC1S7 * ip[1*8 + off]) >> 16; t2 = (xC7S1 * ip[7*8 + off]) >> 16; _A = t1 + t2; t1 = (xC7S1 * ip[1*8 + off]) >> 16; t2 = (xC1S7 * ip[7*8 + off]) >> 16; _B = t1 - t2; t1 = (xC3S5 * ip[3*8 + off]) >> 16; t2 = (xC5S3 * ip[5*8 + off]) >> 16; _C = t1 + t2; t1 = (xC3S5 * ip[5*8 + off]) >> 16; t2 = (xC5S3 * ip[3*8 + off]) >> 16; _D = t1 - t2; _Ad = (xC4S4 * (short)(_A - _C)) >> 16; _Bd = (xC4S4 * (short)(_B - _D)) >> 16; _Cd = _A + _C; _Dd = _B + _D; _E = (xC4S4 * (short)(ip[0*8 + off] + ip[4*8 + off])) >> 16; _F = (xC4S4 * (short)(ip[0*8 + off] - ip[4*8 + off])) >> 16; t1 = (xC2S6 * ip[2*8 + off]) >> 16; t2 = (xC6S2 * ip[6*8 + off]) >> 16; _G = t1 + t2; t1 = (xC6S2 * ip[2*8 + off]) >> 16; t2 = (xC2S6 * ip[6*8 + off]) >> 16; _H = t1 - t2; _Ed = _E - _G; _Gd = _E + _G; _Add = _F + _Ad; _Bdd = _Bd - _H; _Fd = _F - _Ad; _Hd = _Bd + _H; _Gd += IdctAdjustBeforeShift; _Add += IdctAdjustBeforeShift; _Ed += IdctAdjustBeforeShift; _Fd += IdctAdjustBeforeShift; /* Final sequence of operations over-write original inputs. */ op[0*8 + off] = (short)((_Gd + _Cd ) >> 4); op[7*8 + off] = (short)((_Gd - _Cd ) >> 4); op[1*8 + off] = (short)((_Add + _Hd ) >> 4); op[2*8 + off] = (short)((_Add - _Hd ) >> 4); op[3*8 + off] = (short)((_Ed + _Dd ) >> 4); op[4*8 + off] = (short)((_Ed - _Dd ) >> 4); op[5*8 + off] = (short)((_Fd + _Bdd ) >> 4); op[6*8 + off] = (short)((_Fd - _Bdd ) >> 4); }else{ op[0*8 + off] = 0; op[7*8 + off] = 0; op[1*8 + off] = 0; op[2*8 + off] = 0; op[3*8 + off] = 0; op[4*8 + off] = 0; op[5*8 + off] = 0; op[6*8 + off] = 0; } } } /************************ x x x x 0 0 0 0 x x x 0 0 0 0 0 x x 0 0 0 0 0 0 x 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 *************************/ private final void dequant_slow10 (short[] dequant_coeffs, short[] quantized_list, int[] DCT_block) { for(int i=0; i<32; i++) DCT_block[i] = 0; for(int i=0; i<10; i++) DCT_block[Constants.dequant_index[i]] = quantized_list[i] * dequant_coeffs[i]; } public final void IDct10 (short[] InputData, short[]QuantMatrix, short[] OutputData) { short[] op = OutputData; int _A, _B, _C, _D, _Ad, _Bd, _Cd, _Dd, _E, _F, _G, _H; int _Ed, _Gd, _Add, _Bdd, _Fd, _Hd; dequant_slow10 (QuantMatrix, InputData, ip); /* Inverse DCT on the rows now */ for (int loop = 0, off = 0; loop < 4; loop++, off += 8){ /* Check for non-zero values */ if ((ip[0 + off] | ip[1 + off] | ip[2 + off] | ip[3 + off]) != 0 ){ _A = (xC1S7 * ip[1 + off]) >> 16; _B = (xC7S1 * ip[1 + off]) >> 16; _C = (xC3S5 * ip[3 + off]) >> 16; _D = -((xC5S3 * ip[3 + off]) >> 16); _Ad = (xC4S4 * (short)(_A - _C)) >> 16; _Bd = (xC4S4 * (short)(_B - _D)) >> 16; _Cd = _A + _C; _Dd = _B + _D; _E = (xC4S4 * ip[0 + off] ) >> 16; _F = _E; _G = (xC2S6 * ip[2 + off]) >> 16; _H = (xC6S2 * ip[2 + off]) >> 16; _Ed = _E - _G; _Gd = _E + _G; _Add = _F + _Ad; _Bdd = _Bd - _H; _Fd = _F - _Ad; _Hd = _Bd + _H; /* Final sequence of operations over-write original inputs. */ ip[0 + off] = (short)((_Gd + _Cd ) >> 0); ip[7 + off] = (short)((_Gd - _Cd ) >> 0); ip[1 + off] = (short)((_Add + _Hd ) >> 0); ip[2 + off] = (short)((_Add - _Hd ) >> 0); ip[3 + off] = (short)((_Ed + _Dd ) >> 0); ip[4 + off] = (short)((_Ed - _Dd ) >> 0); ip[5 + off] = (short)((_Fd + _Bdd ) >> 0); ip[6 + off] = (short)((_Fd - _Bdd ) >> 0); } } for (int loop = 0, off = 0; loop < 8; loop++, off++) { /* Check for non-zero values (bitwise or faster than ||) */ if ((ip[0*8 + off] | ip[1*8 + off] | ip[2*8 + off] | ip[3*8 + off]) != 0) { _A = (xC1S7 * ip[1*8 + off]) >> 16; _B = (xC7S1 * ip[1*8 + off]) >> 16; _C = (xC3S5 * ip[3*8 + off]) >> 16; _D = -((xC5S3 * ip[3*8 + off]) >> 16); _Ad = (xC4S4 * (short)(_A - _C)) >> 16; _Bd = (xC4S4 * (short)(_B - _D)) >> 16; _Cd = _A + _C; _Dd = _B + _D; _E = (xC4S4 * ip[0*8 + off]) >> 16; _F = _E; _G = (xC2S6 * ip[2*8 + off]) >> 16; _H = (xC6S2 * ip[2*8 + off]) >> 16; _Ed = _E - _G; _Gd = _E + _G; _Add = _F + _Ad; _Bdd = _Bd - _H; _Fd = _F - _Ad; _Hd = _Bd + _H; _Gd += IdctAdjustBeforeShift; _Add += IdctAdjustBeforeShift; _Ed += IdctAdjustBeforeShift; _Fd += IdctAdjustBeforeShift; /* Final sequence of operations over-write original inputs. */ op[0*8 + off] = (short)((_Gd + _Cd ) >> 4); op[7*8 + off] = (short)((_Gd - _Cd ) >> 4); op[1*8 + off] = (short)((_Add + _Hd ) >> 4); op[2*8 + off] = (short)((_Add - _Hd ) >> 4); op[3*8 + off] = (short)((_Ed + _Dd ) >> 4); op[4*8 + off] = (short)((_Ed - _Dd ) >> 4); op[5*8 + off] = (short)((_Fd + _Bdd ) >> 4); op[6*8 + off] = (short)((_Fd - _Bdd ) >> 4); }else{ op[0*8 + off] = 0; op[7*8 + off] = 0; op[1*8 + off] = 0; op[2*8 + off] = 0; op[3*8 + off] = 0; op[4*8 + off] = 0; op[5*8 + off] = 0; op[6*8 + off] = 0; } } } /*************************** x 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 **************************/ public final void IDct1( short[] InputData, short[]QuantMatrix, short[] OutputData ){ short OutD=(short) ((int)(InputData[0]*QuantMatrix[0]+15)>>5); for (int loop=0; loop<64; loop++) OutputData[loop]=OutD; } } cortado-0.6.0/src/com/fluendo/jkate/Bitmap.java100644 0 0 2207 11270111317 16450 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; /** * A Bitmap definition. */ public class Bitmap { public int width; public int height; public int bpp; public KateBitmapType type; public int palette; public byte[] pixels; public int size; public int x_offset; public int y_offset; } cortado-0.6.0/src/com/fluendo/jkate/Bitwise.java100644 0 0 7073 11274615664 16672 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; import com.jcraft.jogg.*; /** * Various methods to read data from a bitstream. */ public class Bitwise { /** * Read a number of bytes into a buffer. */ static void readbuf(Buffer opb, byte[] buf, int len) { for (int i=0; i 0) { int sign = 0; if (head > 0) sign = opb.read1(); int v = opb.read(bits); v <<= tail; if (sign != 0) v = -v; values[n++] = v; } return values; } static private double fixedToFloat(int v) { return ((double)v) / (1<<16); } /** * Read an array of float channels. * Float format defined in the Kate specification. */ static double[][] readFloats(Buffer opb, int count, int streams) { if (count*streams == 0) return null; if (streams > 1) { if (opb.read1() != 0) { count *= streams; streams = 1; } } double values[][] = new double[streams][]; for (int s=0; s * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; public class Color { public byte r; public byte g; public byte b; public byte a; } cortado-0.6.0/src/com/fluendo/jkate/Comment.java100644 0 0 2117 11270111317 16636 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; /** * Vorbis comments are used in Kate streams too. */ public class Comment { String[] user_comments; String vendor; public void clear() { user_comments = null; vendor = null; } } cortado-0.6.0/src/com/fluendo/jkate/Curve.java100644 0 0 2036 11270111317 16320 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; /** * A curve definition, splines, segments, etc. */ public class Curve { public KateCurveType type; public int npts; public double pts[][]; } cortado-0.6.0/src/com/fluendo/jkate/Decode.java100644 0 0 14524 11274615664 16466 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; import com.jcraft.jogg.*; public final class Decode { Buffer opb = new Buffer(); Info info; public Decode (Info i) { info = i; } /** * Decode a text data packet (packet type 0x00), and fills the passed event * from the decoded data. */ int decodeTextPacket(Event ev) { ev.ki = info; ev.start = Bitwise.read64(opb); ev.duration = Bitwise.read64(opb); ev.backlink = Bitwise.read64(opb); ev.start_time = granuleDuration(ev.start); ev.end_time = ev.start_time+granuleDuration(ev.duration); /* text */ int len = Bitwise.read32(opb); ev.text = new byte[len]; Bitwise.readbuf(opb, ev.text, len); /* event ID */ ev.id = -1; if (opb.read1() != 0) { ev.id = Bitwise.read32v(opb); } /* motions */ ev.motions = null; if (opb.read1() != 0) { int nmotions = Bitwise.read32v(opb); if (nmotions < 0) return -1; ev.motions = new Motion[nmotions]; for (int n=0; n= info.motions.length) return -1; ev.motions[n] = info.motions[idx]; } else { try { ev.motions[n] = info.unpackMotion(opb); } catch (KateException ke) { return Result.KATE_E_BAD_PACKET; } } } } /* overrides */ if (opb.read1() != 0) { try { if (opb.read1() != 0) ev.text_encoding = KateTextEncoding.CreateTextEncoding(opb.read(8)); if (opb.read1() != 0) ev.text_directionality = KateTextDirectionality.CreateTextDirectionality(opb.read(8)); } catch (KateException ke) { return Result.KATE_E_BAD_PACKET; } /* language override */ if (opb.read1() != 0) { int nbytes = Bitwise.read32v(opb); if (nbytes < 0) return Result.KATE_E_BAD_PACKET; if (nbytes > 0) { ev.language=new byte[nbytes]; Bitwise.readbuf(opb, ev.language, nbytes); } } /* region override */ if (opb.read1() != 0) { int idx = Bitwise.read32v(opb); if (idx < 0 || idx >= info.regions.length) return Result.KATE_E_BAD_PACKET; ev.kr = info.regions[idx]; } if (opb.read1() != 0) { try { ev.kr = info.unpackRegion(opb); } catch (KateException ke) { return Result.KATE_E_BAD_PACKET; } } /* style override */ if (opb.read1() != 0) { int idx = Bitwise.read32v(opb); if (idx < 0 || idx >= info.styles.length) return Result.KATE_E_BAD_PACKET; ev.ks = info.styles[idx]; } if (opb.read1() != 0) { try { ev.ks = info.unpackStyle(opb); } catch (KateException ke) { return Result.KATE_E_BAD_PACKET; } } if (opb.read1() != 0) { int idx = Bitwise.read32v(opb); if (idx < 0 || idx >= info.styles.length) return Result.KATE_E_BAD_PACKET; ev.ks2 = info.styles[idx]; } if (opb.read1() != 0) { try { ev.ks2 = info.unpackStyle(opb); } catch (KateException ke) { return Result.KATE_E_BAD_PACKET; } } /* font mapping */ if (opb.read1() != 0) { int idx = Bitwise.read32v(opb); if (idx < 0 || idx >= info.font_mappings.length) return Result.KATE_E_BAD_PACKET; ev.font_mapping = info.font_mappings[idx]; } } /* new in 0.2: palettes/bitmaps/markup type */ if (((info.bitstream_version_major<<8) | info.bitstream_version_minor) >= 0x0002) { Bitwise.read32v(opb); if (opb.read1() != 0) { if (opb.read1() != 0) { int idx = Bitwise.read32v(opb); if (idx < 0 || idx >= info.palettes.length) return Result.KATE_E_BAD_PACKET; ev.palette = info.palettes[idx]; } if (opb.read1() != 0) { try { ev.palette = info.unpackPalette(opb); } catch (KateException e) { return Result.KATE_E_BAD_PACKET; } } if (opb.read1() != 0) { int idx = Bitwise.read32v(opb); if (idx < 0 || idx >= info.bitmaps.length) return Result.KATE_E_BAD_PACKET; ev.bitmap = info.bitmaps[idx]; } if (opb.read1() != 0) { try { ev.bitmap = info.unpackBitmap(opb); } catch (KateException e) { return Result.KATE_E_BAD_PACKET; } } if (opb.read1() != 0) { try { ev.markup_type = KateMarkupType.CreateMarkupType(opb.read(8)); } catch (KateException e) { return Result.KATE_E_BAD_PACKET; } } } } // TODO: remainder return 0; } /** * Convert a granule to a time. */ public double granuleTime(long granulepos) { if(granulepos>=0){ long base=granulepos>>info.granule_shift; long offset=granulepos-(base<=0){ return (granule)* ((double)info.gps_denominator/info.gps_numerator); } return(-1); } } cortado-0.6.0/src/com/fluendo/jkate/Event.java100644 0 0 3563 11270111317 16323 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; public class Event { public Info ki = null; public long start; public long duration; public long backlink; public double start_time; public double end_time; public int id = -1; public KateTextEncoding text_encoding; public KateTextDirectionality text_directionality; public KateMarkupType markup_type; public byte[] language; public Region kr = null; public Style ks = null; public Style ks2 = null; public Motion motions[] = null; public Palette palette = null; public Bitmap bitmap = null; public FontMapping font_mapping = null; public byte text[]; /** * Initialize an event to safe defaults. */ public Event(Info ki) { this.ki = ki; id = -1; kr = null; ks = null; ks2 = null; motions = null; palette = null; bitmap = null; text = null; font_mapping = null; text_encoding = ki.text_encoding; text_directionality = ki.text_directionality; markup_type = ki.markup_type; language = null; } } cortado-0.6.0/src/com/fluendo/jkate/FontMapping.java100644 0 0 1776 11270111317 17470 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; /** * A set of ranges defining a mapping from code points to bitmaps. */ class FontMapping { FontRange ranges[]; } cortado-0.6.0/src/com/fluendo/jkate/FontRange.java100644 0 0 2041 11270111317 17113 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; /** * A code point range mapping to a set of bitmaps. */ public class FontRange { int first_code_point; int last_code_point; int first_bitmap; } cortado-0.6.0/src/com/fluendo/jkate/Info.java100644 0 0 45323 11350725171 16165 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; import com.jcraft.jogg.*; import com.fluendo.utils.*; public class Info { public int bitstream_version_major = -1; public int bitstream_version_minor = -1; public KateTextEncoding text_encoding; public KateTextDirectionality text_directionality; public int num_headers = 0; public int granule_shift; public int gps_numerator; public int gps_denominator; public String language; public String category; public Region regions[]; public Style styles[]; public Curve curves[]; public Motion motions[]; public Palette palettes[]; public Bitmap bitmaps[]; public FontRange font_ranges[]; public FontMapping font_mappings[]; public KateMarkupType markup_type; public int original_canvas_width; public int original_canvas_height; /* used to track which header we need to decode next */ private int probe = 0; /** * Read a packet canvas size (width or height). * Format defined in the Kate specification. */ private static int read_canvas_size(Buffer opb) { int value, base, shift; value = opb.read(8) | (opb.read(8)<<8); base = value>>4; shift = value&15; return base< 0) return Result.KATE_E_VERSION; num_headers = (int)opb.read(8); if (num_headers < 1) return Result.KATE_E_BAD_PACKET; tmp = opb.read(8); if (tmp != 0) return Result.KATE_E_BAD_PACKET; try { text_encoding = KateTextEncoding.CreateTextEncoding(tmp); text_directionality = KateTextDirectionality.CreateTextDirectionality(opb.read(8)); } catch (KateException e) { return Result.KATE_E_BAD_PACKET; } reserved = opb.read(8); if (bitstream_version_major==0 && bitstream_version_minor<3) { if (reserved != 0) return Result.KATE_E_BAD_PACKET; } granule_shift = opb.read(8); original_canvas_width = read_canvas_size(opb); original_canvas_height = read_canvas_size(opb); reserved = Bitwise.read32(opb); if (bitstream_version_major==0 && bitstream_version_minor<3) { if (reserved != 0) return Result.KATE_E_BAD_PACKET; } gps_numerator = Bitwise.read32(opb); gps_denominator = Bitwise.read32(opb); if (granule_shift >= 64) return Result.KATE_E_BAD_PACKET; if (gps_numerator == 0 || gps_denominator == 0) return Result.KATE_E_BAD_PACKET; byte[] buffer16=new byte[16]; int buffer_characters; language = ""; buffer_characters = 0; Bitwise.readbuf(opb, buffer16, 16); if (buffer16[15] != 0) return Result.KATE_E_BAD_PACKET; for (buffer_characters=0; buffer_characters<16; ++buffer_characters) { if (buffer16[buffer_characters] == 0) break; } language = new String(buffer16, 0, buffer_characters); category = ""; buffer_characters = 0; Bitwise.readbuf(opb, buffer16, 16); if (buffer16[15] != 0) return Result.KATE_E_BAD_PACKET; for (buffer_characters=0; buffer_characters<16; ++buffer_characters) { if (buffer16[buffer_characters] == 0) break; } category = new String(buffer16, 0, buffer_characters); /* end of packet */ if (opb.read(1) != -1) return (Result.KATE_E_BAD_PACKET); return(0); } /** * Checks that we have reached the end of the packet. */ static int checkEOP(Buffer opb) { int bits = 7 & (8 - (opb.bits()&7)); if (bits > 0) { if (opb.read(bits) != 0) return Result.KATE_E_BAD_PACKET; } if (opb.look1() != -1) return (Result.KATE_E_BAD_PACKET); return 0; } /** * Decodes a Vorbis comment packet. * straight copy of the jheora one */ private int unpackComment (Comment kc, Buffer opb) { int i; int len; byte[] tmp; int comments; len = Bitwise.read32(opb); if(len<0) return(Result.KATE_E_BAD_PACKET); tmp=new byte[len]; Bitwise.readbuf(opb, tmp, len); kc.vendor=new String(tmp); comments = Bitwise.read32(opb); if(comments<0) { kc.clear(); return Result.KATE_E_BAD_PACKET; } kc.user_comments=new String[comments]; for(i=0;i= 0x0002) { Bitwise.read32v(opb); kr.clip = (opb.read1() != 0); } else { kr.clip = false; } Bitwise.skipWarp(opb); return kr; } /** * Decode the regions header packet. */ private int unpackRegions (Buffer opb) { int nregions = Bitwise.read32v(opb); if (nregions < 0) return Result.KATE_E_BAD_PACKET; regions = new Region[nregions]; for (int n=0; n= 0x0002) { Bitwise.read32v(opb); ks.justify = opb.read1() != 0; int len = Bitwise.read32v(opb); if (len < 0) throw new KateBadPacketException(); byte s[] = new byte[len]; Bitwise.readbuf(opb, s, len); ks.font = new String(s); } else { ks.justify = false; ks.font = null; } if (((bitstream_version_major<<8) | bitstream_version_minor) >= 0x0004) { Bitwise.read32v(opb); ks.wrap_mode = KateWrapMode.CreateWrapMode(Bitwise.read32v(opb)); } else { ks.wrap_mode = KateWrapMode.kate_wrap_word; } Bitwise.skipWarp(opb); return ks; } /** * Decode the styles header packet. */ private int unpackStyles (Buffer opb) { int nstyles = Bitwise.read32v(opb); if (nstyles < 0) return Result.KATE_E_BAD_PACKET; styles = new Style[nstyles]; for (int n=0; n= this.curves.length) throw new KateBadPacketException(); km.curves[n] = this.curves[idx]; } else { km.curves[n] = unpackCurve(opb); } } double floats[][] = Bitwise.readFloats(opb, ncurves, 1); km.durations = new double[ncurves]; for (int n=0; n 8) throw new KateBadPacketException(); if (kb.bpp == 0) { kb.type = KateBitmapType.CreateBitmapType(opb.read(8)); kb.palette = -1; if (kb.type == KateBitmapType.kate_bitmap_type_paletted) { int encoding = opb.read(8); switch (encoding) { case 1: /* RLE */ kb.bpp = Bitwise.read32v(opb); kb.palette = Bitwise.read32v(opb); kb.pixels = RLE.decodeRLE(opb, kb.width, kb.height, kb.bpp); break; default: Debug.warning("Unsupported bitmap type"); throw new KateBadPacketException(); } } else if (kb.type == KateBitmapType.kate_bitmap_type_png) { kb.size = Bitwise.read32(opb); kb.pixels = new byte[kb.size]; Bitwise.readbuf(opb, kb.pixels, kb.size); } else { Debug.warning("Unsupported bitmap type"); throw new KateBadPacketException(); } } else { kb.type = KateBitmapType.kate_bitmap_type_paletted; kb.palette = Bitwise.read32v(opb); int npixels = kb.width * kb.height; kb.pixels = new byte[npixels]; for (int n=0; n= 0x0004) { Bitwise.read32v(opb); kb.x_offset = Bitwise.read32v(opb); kb.y_offset = Bitwise.read32v(opb); } else { kb.x_offset = 0; kb.y_offset = 0; } Bitwise.skipWarp(opb); return kb; } /** * Decodes the bitmaps packet. */ private int unpackBitmaps (Buffer opb) { int nbitmaps = Bitwise.read32v(opb); if (nbitmaps < 0) return Result.KATE_E_BAD_PACKET; bitmaps = new Bitmap[nbitmaps]; for (int n=0; n 0) { font_ranges = new FontRange[nranges]; for (int n=0; n 0) { font_mappings = new FontMapping[nmappings]; for (int n=0; n 0) { FontRange fr[] = new FontRange[nranges]; for (int l=0; l= this.font_ranges.length) return Result.KATE_E_BAD_PACKET; fr[l] = this.font_ranges[idx]; } else { fr[l] = unpackFontRange(opb); } } font_mappings[n].ranges = fr; } else { font_mappings[n] = null; } } } Bitwise.skipWarp(opb); /* end of packet */ return checkEOP(opb); } /** * Resets the header decoder to the start, so a new stream may be decoded. */ public void clear() { num_headers = 0; regions = null; styles = null; curves = null; motions = null; probe = 0; } /** * Decodes a Kate header, updating the info with the data decoded from the header. * If the next expected header is decoded properly, the next header will be expected. * Headers beyond the ones we know about are ignored. */ public int decodeHeader (Comment kc, Packet op) { long ret; Buffer opb = new Buffer(); opb.readinit (op.packet_base, op.packet, op.bytes); { byte[] id = new byte[7]; int typeflag; typeflag = opb.read(8); /* header types have the MSB set */ if((typeflag & 0x80) == 0) { return Result.KATE_E_BAD_PACKET; } /* Kate header magic */ Bitwise.readbuf(opb,id,7); if (!"kate\0\0\0".equals(new String(id))) { return Result.KATE_E_NOT_KATE; } if (op.packetno < num_headers) { if (probe != op.packetno) return Result.KATE_E_BAD_PACKET; } /* reserved 0 byte */ if (opb.read(8) != 0) return Result.KATE_E_BAD_PACKET; Debug.debug("decodeHeader: packet type "+typeflag+", probe "+probe); /* ensure packets are received in order */ switch(probe){ case 0: if(op.b_o_s == 0){ /* Not the initial packet */ return Result.KATE_E_BAD_PACKET; } ret = unpackInfo(opb); break; case 1: ret = unpackComment(kc,opb); break; case 2: ret = unpackRegions(opb); break; case 3: ret = unpackStyles(opb); break; case 4: ret = unpackCurves(opb); break; case 5: ret = unpackMotions(opb); break; case 6: ret = unpackPalettes(opb); break; case 7: ret = unpackBitmaps(opb); break; case 8: ret = unpackFontMappings(opb); /* last known header, we can init for decode */ if (ret == 0) { Debug.debug("Found last known header, returning 1"); ret = 1; } break; default: /* ignore any trailing header packets for forward compatibility */ ret = 0; break; } } /* decode was successful, we're now expecting the next packet in sequence */ if (ret >= 0) { ++probe; } return (int)ret; } } cortado-0.6.0/src/com/fluendo/jkate/KateBadPacketException.java100644 0 0 2055 11274615664 21561 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; class KateBadPacketException extends KateException { public KateBadPacketException() { super("Bad packet"); } private static final long serialVersionUID = 1L; } cortado-0.6.0/src/com/fluendo/jkate/KateBitmapType.java100644 0 0 2773 11270111317 20127 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; public class KateBitmapType { public static final KateBitmapType kate_bitmap_type_paletted = new KateBitmapType (); public static final KateBitmapType kate_bitmap_type_png = new KateBitmapType (); private static final KateBitmapType[] list = { kate_bitmap_type_paletted, kate_bitmap_type_png, }; private KateBitmapType() { } /** * Create a KateBitmapType object from an integer. */ public static KateBitmapType CreateBitmapType(int idx) throws KateException { if (idx < 0 || idx >= list.length) throw new KateException("Bitmap type "+idx+" out of bounds"); return list[idx]; } } cortado-0.6.0/src/com/fluendo/jkate/KateCurveType.java100644 0 0 3636 11270111317 17776 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; public class KateCurveType { public static final KateCurveType kate_curve_none = new KateCurveType (); public static final KateCurveType kate_curve_static = new KateCurveType (); public static final KateCurveType kate_curve_linear = new KateCurveType (); public static final KateCurveType kate_curve_catmull_rom_spline = new KateCurveType (); public static final KateCurveType kate_curve_bezier_cubic_spline = new KateCurveType (); public static final KateCurveType kate_curve_bspline = new KateCurveType (); private static final KateCurveType[] list = { kate_curve_none, kate_curve_static, kate_curve_linear, kate_curve_catmull_rom_spline, kate_curve_bezier_cubic_spline, kate_curve_bspline, }; private KateCurveType() { } /** * Create a KateCurveType object from an integer. */ public static KateCurveType CreateCurveType(int idx) throws KateException { if (idx < 0 || idx >= list.length) throw new KateException("Curve type "+idx+" out of bounds"); return list[idx]; } } cortado-0.6.0/src/com/fluendo/jkate/KateException.java100644 0 0 2035 11274615664 20020 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; class KateException extends java.lang.Exception { public KateException(String s) { super(); } private static final long serialVersionUID = 1L; } cortado-0.6.0/src/com/fluendo/jkate/KateMarkupType.java100644 0 0 2745 11270111317 20151 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; public class KateMarkupType { public static final KateMarkupType kate_markup_none = new KateMarkupType (); public static final KateMarkupType kate_markup_simple = new KateMarkupType (); private static final KateMarkupType[] list = { kate_markup_none, kate_markup_simple, }; private KateMarkupType() { } /** * Create a KateMarkupType object from an integer. */ public static KateMarkupType CreateMarkupType(int idx) throws KateException { if (idx < 0 || idx >= list.length) throw new KateException("Markup type "+idx+" out of bounds"); return list[idx]; } } cortado-0.6.0/src/com/fluendo/jkate/KateMotionMapping.java100644 0 0 3572 11270111317 20630 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; public class KateMotionMapping { public static final KateMotionMapping kmm_none = new KateMotionMapping (); public static final KateMotionMapping kmm_frame = new KateMotionMapping (); public static final KateMotionMapping kmm_window = new KateMotionMapping (); public static final KateMotionMapping kmm_region = new KateMotionMapping (); public static final KateMotionMapping kmm_event_duration = new KateMotionMapping (); public static final KateMotionMapping kmm_bitmap_size = new KateMotionMapping (); private static final KateMotionMapping[] list = { kmm_none, kmm_frame, kmm_window, kmm_region, kmm_event_duration, kmm_bitmap_size, }; private KateMotionMapping() { } /** * Create a KateMotionMapping object from an integer. */ public static KateMotionMapping CreateMotionMapping(int idx) throws KateException { if (idx < 0 || idx >= list.length) throw new KateException("Motion mapping "+idx+" out of bounds"); return list[idx]; } } cortado-0.6.0/src/com/fluendo/jkate/KateMotionSemantics.java100644 0 0 13526 11270111317 21203 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; public class KateMotionSemantics { public static final KateMotionSemantics kms_time = new KateMotionSemantics (); public static final KateMotionSemantics kms_z = new KateMotionSemantics (); public static final KateMotionSemantics kms_region_position = new KateMotionSemantics (); public static final KateMotionSemantics kms_region_size = new KateMotionSemantics (); public static final KateMotionSemantics kms_text_alignment_int = new KateMotionSemantics (); public static final KateMotionSemantics kms_text_alignment_ext = new KateMotionSemantics (); public static final KateMotionSemantics kms_text_position = new KateMotionSemantics (); public static final KateMotionSemantics kms_text_size = new KateMotionSemantics (); public static final KateMotionSemantics kms_marker1_position = new KateMotionSemantics (); public static final KateMotionSemantics kms_marker2_position = new KateMotionSemantics (); public static final KateMotionSemantics kms_marker3_position = new KateMotionSemantics (); public static final KateMotionSemantics kms_marker4_position = new KateMotionSemantics (); public static final KateMotionSemantics kms_glyph_pointer_1 = new KateMotionSemantics (); public static final KateMotionSemantics kms_glyph_pointer_2 = new KateMotionSemantics (); public static final KateMotionSemantics kms_glyph_pointer_3 = new KateMotionSemantics (); public static final KateMotionSemantics kms_glyph_pointer_4 = new KateMotionSemantics (); public static final KateMotionSemantics kms_text_color_rg = new KateMotionSemantics (); public static final KateMotionSemantics kms_text_color_ba = new KateMotionSemantics (); public static final KateMotionSemantics kms_background_color_rg = new KateMotionSemantics (); public static final KateMotionSemantics kms_background_color_ba = new KateMotionSemantics (); public static final KateMotionSemantics kms_draw_color_rg = new KateMotionSemantics (); public static final KateMotionSemantics kms_draw_color_ba = new KateMotionSemantics (); public static final KateMotionSemantics kms_style_morph = new KateMotionSemantics (); public static final KateMotionSemantics kms_text_path = new KateMotionSemantics (); public static final KateMotionSemantics kms_text_path_section = new KateMotionSemantics (); public static final KateMotionSemantics kms_draw = new KateMotionSemantics (); public static final KateMotionSemantics kms_text_visible_section = new KateMotionSemantics (); public static final KateMotionSemantics kms_horizontal_margins = new KateMotionSemantics (); public static final KateMotionSemantics kms_vertical_margins = new KateMotionSemantics (); public static final KateMotionSemantics kms_bitmap_position = new KateMotionSemantics (); public static final KateMotionSemantics kms_bitmap_size = new KateMotionSemantics (); public static final KateMotionSemantics kms_marker1_bitmap = new KateMotionSemantics (); public static final KateMotionSemantics kms_marker2_bitmap = new KateMotionSemantics (); public static final KateMotionSemantics kms_marker3_bitmap = new KateMotionSemantics (); public static final KateMotionSemantics kms_marker4_bitmap = new KateMotionSemantics (); public static final KateMotionSemantics kms_glyph_pointer_1_bitmap = new KateMotionSemantics (); public static final KateMotionSemantics kms_glyph_pointer_2_bitmap = new KateMotionSemantics (); public static final KateMotionSemantics kms_glyph_pointer_3_bitmap = new KateMotionSemantics (); public static final KateMotionSemantics kms_glyph_pointer_4_bitmap = new KateMotionSemantics (); public static final KateMotionSemantics kms_draw_width = new KateMotionSemantics (); private static final KateMotionSemantics[] list = { kms_time, kms_z, kms_region_position, kms_region_size, kms_text_alignment_int, kms_text_alignment_ext, kms_text_position, kms_text_size, kms_marker1_position, kms_marker2_position, kms_marker3_position, kms_marker4_position, kms_glyph_pointer_1, kms_glyph_pointer_2, kms_glyph_pointer_3, kms_glyph_pointer_4, kms_text_color_rg, kms_text_color_ba, kms_background_color_rg, kms_background_color_ba, kms_draw_color_rg, kms_draw_color_ba, kms_style_morph, kms_text_path, kms_text_path_section, kms_draw, kms_text_visible_section, kms_horizontal_margins, kms_vertical_margins, kms_bitmap_position, kms_bitmap_size, kms_marker1_bitmap, kms_marker2_bitmap, kms_marker3_bitmap, kms_marker4_bitmap, kms_glyph_pointer_1_bitmap, kms_glyph_pointer_2_bitmap, kms_glyph_pointer_3_bitmap, kms_glyph_pointer_4_bitmap, kms_draw_width, }; private KateMotionSemantics() { } /** * Create a KateMotionSemantics object from an integer. */ public static KateMotionSemantics CreateMotionSemantics(int idx) throws KateException { if (idx < 0 || idx >= list.length) throw new KateException("Motion semantics "+idx+" out of bounds"); return list[idx]; } } cortado-0.6.0/src/com/fluendo/jkate/KateSpaceMetric.java100644 0 0 3160 11270111317 20237 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; public class KateSpaceMetric { public static final KateSpaceMetric kate_metric_pixels = new KateSpaceMetric (); public static final KateSpaceMetric kate_metric_percentage = new KateSpaceMetric (); public static final KateSpaceMetric kate_metric_millionths = new KateSpaceMetric (); private static final KateSpaceMetric[] list = { kate_metric_pixels, kate_metric_percentage, kate_metric_millionths, }; private KateSpaceMetric() { } /** * Create a KateSpaceMetric object from an integer. */ public static KateSpaceMetric CreateSpaceMetric(int idx) throws KateException { if (idx < 0 || idx >= list.length) throw new KateException("Space metrics "+idx+" out of bounds"); return list[idx]; } } cortado-0.6.0/src/com/fluendo/jkate/KateTextDirectionality.java100644 0 0 3402 11270111317 21667 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; public class KateTextDirectionality { public static final KateTextDirectionality kate_l2r_t2b = new KateTextDirectionality (); public static final KateTextDirectionality kate_r2l_t2b = new KateTextDirectionality (); public static final KateTextDirectionality kate_t2b_r2l = new KateTextDirectionality (); public static final KateTextDirectionality kate_t2b_l2r = new KateTextDirectionality (); private static final KateTextDirectionality[] list = { kate_l2r_t2b, kate_r2l_t2b, kate_t2b_r2l, kate_t2b_l2r }; private KateTextDirectionality() { } /** * Create a KateTextDirectionality object from an integer. */ public static KateTextDirectionality CreateTextDirectionality(int idx) throws KateException { if (idx < 0 || idx >= list.length) throw new KateException("Text directionality "+idx+" out of bounds"); return list[idx]; } } cortado-0.6.0/src/com/fluendo/jkate/KateTextEncoding.java100644 0 0 2600 11270111317 20431 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; public class KateTextEncoding { public static final KateTextEncoding kate_utf8 = new KateTextEncoding (); private static final KateTextEncoding[] list = { kate_utf8, }; private KateTextEncoding() { } /** * Create a KateTextEncoding object from an integer. */ public static KateTextEncoding CreateTextEncoding(int idx) throws KateException { if (idx < 0 || idx >= list.length) throw new KateException("Text encoding "+idx+" out of bounds"); return list[idx]; } } cortado-0.6.0/src/com/fluendo/jkate/KateWrapMode.java100644 0 0 2703 11270111317 17560 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; public class KateWrapMode { public static final KateWrapMode kate_wrap_word = new KateWrapMode (); public static final KateWrapMode kate_wrap_none = new KateWrapMode (); private static final KateWrapMode[] list = { kate_wrap_word, kate_wrap_none, }; private KateWrapMode() { } /** * Create a KateWrapMode object from an integer. */ public static KateWrapMode CreateWrapMode(int idx) throws KateException { if (idx < 0 || idx >= list.length) throw new KateException("Wrap mode "+idx+" out of bounds"); return list[idx]; } } cortado-0.6.0/src/com/fluendo/jkate/Motion.java100644 0 0 2210 11270111317 16473 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; /** * A motion definition, composed of a series of curves */ public class Motion { public Curve curves[]; public double durations[]; KateMotionMapping x_mapping; KateMotionMapping y_mapping; KateMotionSemantics semantics; boolean periodic; } cortado-0.6.0/src/com/fluendo/jkate/Palette.java100644 0 0 2006 11270111317 16627 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; /** * A Palette definition, containing between 0 and 256 colors. */ public class Palette { public Color colors[] = null; } cortado-0.6.0/src/com/fluendo/jkate/RLE.java100644 0 0 22463 11270111317 15704 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; import com.jcraft.jogg.*; /** * RLE decoding routines. */ public class RLE { private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC = 4; private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_IN_DELTA = 3; private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_STARTEND = 3; private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_STOP = 6; private static final int KATE_RLE_RUN_LENGTH_BITS_DELTA = 6; private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_STARTEND_START = 9; private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_STARTEND_END = 8; private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_STOP_START = 8; private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_IN_DELTA_STOP = 3; private static final int KATE_RLE_RUN_LENGTH_BITS_DELTA_STOP = 5; private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_ZERO = 8; private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_NON_ZERO = 3; private static final int KATE_RLE_TYPE_EMPTY = 0; private static final int KATE_RLE_TYPE_BASIC = 1; private static final int KATE_RLE_TYPE_DELTA = 2; private static final int KATE_RLE_TYPE_BASIC_STOP = 3; private static final int KATE_RLE_TYPE_BASIC_STARTEND = 4; private static final int KATE_RLE_TYPE_DELTA_STOP = 5; private static final int KATE_RLE_TYPE_BASIC_ZERO = 6; private static final int KATE_RLE_TYPE_BITS = 3; private static int decodeLineEmpty(Buffer opb, int width, byte pixels[], int offset, int bits, byte zero) { for (int n=0; n 0) { int run_length = 1+opb.read(run_length_bits); if (run_length == 0 || run_length > count) return -1; byte value = (byte)opb.read(bits); for (int n=0; n 0) { int type = opb.read1(); if (type != 0) { int run_length = 1+opb.read(run_length_delta_bits); if (run_length == 0 || run_length > count) return -1; if (offset > 0) { for (int n=0; n count) return -1; byte value = (byte)opb.read(bits); for (int n=0; n 0) { if (run_length > count) return -1; for (int n=0; n 0) { if (run_length > count) return -1; for (int n=0; n 0) { run_length = 1 + opb.read(run_length_bits); if (run_length == 0 || run_length > count) return -1; byte value = (byte)opb.read(bits); for (int n=0; n 0) { if (run_length > count) return -1; for (int n=0; n 0) { run_length = opb.read(run_length_bits); if (run_length > count) return -1; if (run_length == 0) { for (int n=0; n 0) { int type = opb.read1(); if (type != 0) { run_length = 1 + opb.read(run_length_delta_bits); if (run_length == 0 || run_length > count) return -1; if (offset > 0) { for (int n=0; n count) return -1; byte value = (byte)opb.read(bits); for (int n=0; n 0) { byte value = (byte)opb.read(bits); if (value == zero) { run_length = 1 + opb.read(run_length_bits_zero); } else { run_length = 1 + opb.read(run_length_bits_non_zero); } if (run_length == 0 || run_length > count) return -1; for (int n=0; n 0) { int type = opb.read(KATE_RLE_TYPE_BITS); switch (type) { case KATE_RLE_TYPE_EMPTY: ret = decodeLineEmpty(opb, width, pixels, offset, bpp, zero); break; case KATE_RLE_TYPE_DELTA: ret = decodeLineDelta(opb, width, pixels, offset, bpp, zero); break; case KATE_RLE_TYPE_BASIC: ret = decodeLineBasic(opb, width, pixels, offset, bpp, zero); break; case KATE_RLE_TYPE_BASIC_STARTEND: ret = decodeLineBasicStartEnd(opb, width, pixels, offset, bpp, zero); break; case KATE_RLE_TYPE_BASIC_STOP: ret = decodeLineBasicStop(opb, width, pixels, offset, bpp, zero); break; case KATE_RLE_TYPE_DELTA_STOP: ret = decodeLineDeltaStop(opb, width, pixels, offset, bpp, zero); break; case KATE_RLE_TYPE_BASIC_ZERO: ret = decodeLineBasicZero(opb, width, pixels, offset, bpp, zero); break; default: return null; } if (ret != 0) return null; offset += width; --height; } return pixels; } } cortado-0.6.0/src/com/fluendo/jkate/Region.java100644 0 0 2151 11270111317 16455 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; /** * A region definition, for placement of text/images. */ public class Region { public KateSpaceMetric metric; public int x; public int y; public int w; public int h; public int style; public boolean clip; } cortado-0.6.0/src/com/fluendo/jkate/Result.java100644 0 0 3073 11270111317 16514 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; public final class Result { public static final int KATE_E_NOT_FOUND = -1; public static final int KATE_E_INVALID_PARAMETER = -2; public static final int KATE_E_OUT_OF_MEMORY = -3; public static final int KATE_E_BAD_GRANULE = -4; public static final int KATE_E_INIT = -5; public static final int KATE_E_BAD_PACKET = -6; public static final int KATE_E_TEXT = -7; public static final int KATE_E_LIMIT = -8; public static final int KATE_E_VERSION = -9; public static final int KATE_E_NOT_KATE = -10; public static final int KATE_E_BAD_TAG = -11; } cortado-0.6.0/src/com/fluendo/jkate/State.java100644 0 0 5332 11270111317 16316 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; import com.jcraft.jogg.*; import com.fluendo.utils.*; public class State { long granulepos; private Decode dec; private Event ev = null; public void clear() { } /** * Initialize for decoding. */ public int decodeInit(Info ki) { dec = new Decode(ki); granulepos=-1; return(0); } /** * Decode a Kate data packet. * Headers are supposed to have been parsed already. * An event may be generated, and will then be available from decodeEventOut. */ public int decodePacketin (Packet op) { long ret; byte type; ev = null; dec.opb.readinit(op.packet_base, op.packet, op.bytes); /* get packet type */ type = (byte)dec.opb.read(8); /* ignore headers */ if ((type & 0x80) != 0) return 0; switch (type) { case 0x00: ev = new Event(dec.info); ret = dec.decodeTextPacket(ev); if(ret < 0) { ev = null; return (int) ret; } if(op.granulepos>-1) granulepos=op.granulepos; else{ if(granulepos==-1){ granulepos=0; } } return 0; case 0x01: /* keepalive */ return 0; case 0x7f: /* eos */ return 1; default: Debug.debug("Kate packet type "+type+" ignored"); return 0; } } /** * Returns the event (if any) generated from the last decoded packet. */ public Event decodeEventOut () { return ev; } /** * Returns, in seconds, absolute time of current packet in given * logical stream */ public double granuleTime(long granulepos) { return dec.granuleTime(granulepos); } /** * Returns, in seconds, duration in granule units */ public double granuleDuration(long granulepos) { return dec.granuleDuration(granulepos); } } cortado-0.6.0/src/com/fluendo/jkate/Style.java100644 0 0 2776 11270111317 16347 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; /** * A style definition. */ public class Style { public double halign; public double valign; public Color text_color; public Color background_color; public Color draw_color; public KateSpaceMetric font_metric; public double font_width; public double font_height; public KateSpaceMetric margin_metric; public double left_margin; public double top_margin; public double right_margin; public double bottom_margin; public boolean bold; public boolean italics; public boolean underline; public boolean strike; public boolean justify; public KateWrapMode wrap_mode; public String font; } cortado-0.6.0/src/com/fluendo/jkate/Tracker.java100644 0 0 5441 11274615664 16654 0ustar 0 0 /* JKate * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JKate are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jkate; import java.awt.*; import com.fluendo.utils.*; public final class Tracker { private Dimension window; private Dimension frame; public com.fluendo.jkate.Event ev = null; public boolean has[] = new boolean[64]; public static final int has_region = 0; public static final int has_text_alignment_int = 1; public static final int has_text_alignment_ext = 2; public float region_x; public float region_y; public float region_w; public float region_h; public Tracker (com.fluendo.jkate.Event ev) { this.ev = ev; } /** * Update the tracker at the given time for the given image's dimensions. */ public boolean update(double t, Dimension window, Dimension frame) { this.window = window; this.frame = frame; /* find current region and style, if any */ Region kr = ev.kr; Style ks = ev.ks; if (ks == null && kr != null && kr.style >= 0) { ks = ev.ki.styles[kr.style]; } /* start with nothing */ for (int n=0; n "+length); data = new byte[length]; } } /** * copies data into the buffer. * * @param data: the bytearray with data to copy * @param offset: offset in the bytearray of first byte * @param length: length of data to copy */ public void copyData (byte[] data, int offset, int length) { ensureSize(length); System.arraycopy (data, offset, this.data, 0, length); this.offset = 0; this.length = length; } } cortado-0.6.0/src/com/fluendo/jst/Bus.java100644 0 0 5676 11270111317 15504 0ustar 0 0 /* Cortado - a video player java applet * Copyright (C) 2004 Fluendo S.L. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. */ package com.fluendo.jst; import java.util.*; import com.fluendo.utils.*; public class Bus { private Vector queue; private Vector handlers; private boolean flushing; private BusSyncHandler syncHandler; public Bus() { queue = new Vector(); handlers = new Vector(); flushing = false; } public synchronized void addHandler (BusHandler handler) { handlers.addElement (handler); } public synchronized void removeHandler (BusHandler handler) { handlers.removeElement (handler); } public synchronized void setSyncHandler (BusSyncHandler handler) { syncHandler = handler; } private void notifyHandlers (Vector handlers, Message message) { Debug.debug("Bus.notifyHandlers: " + message); for (Enumeration e = handlers.elements(); e.hasMoreElements();) { BusHandler handler = (BusHandler) e.nextElement(); Debug.debug("Notifying " + handler); handler.handleMessage (message); } } public void post(Message message) { boolean post = true; BusSyncHandler handler; Debug.debug("Bus.post: " + message); synchronized (this) { if (flushing) return; handler = syncHandler; } post = (handler == null || handler.handleSyncMessage (message) == BusSyncHandler.PASS); synchronized (this) { if (post && !flushing) { queue.addElement (message); notifyAll(); } } } public synchronized Message peek() { if (queue.isEmpty() || flushing) return null; return (Message) queue.firstElement(); } public synchronized Message pop() { Message ret; if (queue.isEmpty() || flushing) return null; ret = (Message) queue.elementAt(0); queue.removeElementAt(0); return ret; } public synchronized Message poll(long timeout) { if (queue.isEmpty() && !flushing) { try { wait(timeout); } catch (InterruptedException e) {} } return pop(); } public synchronized void setFlushing (boolean flush) { flushing = flush; queue.setSize(0); notifyAll(); } public void waitAndDispatch() { Message msg; msg = poll (0); if (msg != null) notifyHandlers (handlers, msg); } } cortado-0.6.0/src/com/fluendo/jst/BusHandler.java100644 0 0 1614 11270111317 16766 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.jst; public interface BusHandler { public void handleMessage (Message message); } cortado-0.6.0/src/com/fluendo/jst/BusSyncHandler.java100644 0 0 1734 11270111317 17626 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.jst; public interface BusSyncHandler { public static final int DROP = 0; public static final int PASS = 1; public int handleSyncMessage (Message message); } cortado-0.6.0/src/com/fluendo/jst/Caps.java100644 0 0 5021 11350725171 15631 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.jst; import java.util.*; public class Caps { protected String mime; protected Hashtable fields = new Hashtable(); public synchronized String getMime () { return mime; } public synchronized void setMime (String newMime) { mime = newMime; } public Caps(String mime) { super(); int sep1, sep2, sep3; int len; len = mime.length(); sep1 = 0; sep2 = mime.indexOf (';'); if (sep2 == -1) sep2 = len; this.mime = mime.substring(0, sep2); while (sep2 < len) { sep1 = sep2+1; sep2 = mime.indexOf ('=', sep1); sep3 = mime.indexOf (';', sep2); if (sep3 == -1) sep3 = len; setField (mime.substring(sep1, sep2), mime.substring(sep2+1, sep3)); sep2 = sep3; } } public String toString () { StringBuffer buf = new StringBuffer(); buf.append("Caps: "); buf.append(mime); buf.append("\n"); for (Enumeration e = fields.keys(); e.hasMoreElements();) { String key = (String) e.nextElement(); buf.append(" \"").append(key).append("\": \"").append(fields.get(key)).append("\"\n"); } return buf.toString(); } public void setField (String key, java.lang.Object value) { fields.put (key, value); } public void setFieldInt (String key, int value) { fields.put (key, new Integer (value)); } public java.lang.Object getField (String key) { return fields.get (key); } public int getFieldInt (String key, int def) { Integer i; i = (Integer) fields.get(key); if (i == null) return def; return i.intValue(); } public String getFieldString (String key, String def) { String s = (String) fields.get(key); if (s == null) return def; return s; } } cortado-0.6.0/src/com/fluendo/jst/CapsListener.java100644 0 0 1606 11270111317 17334 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.jst; public interface CapsListener { public void capsChanged (Caps caps); } cortado-0.6.0/src/com/fluendo/jst/Clock.java100644 0 0 5246 11270111317 15777 0ustar 0 0 /* Cortado - a video player java applet * Copyright (C) 2004 Fluendo S.L. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. */ package com.fluendo.jst; public abstract class Clock { private long adjust; private long lastTime; public static final long USECOND = 1; public static final long MSECOND = 1000 * USECOND; public static final long SECOND = 1000 * MSECOND; /* id types */ public static final int SINGLE = 0; public static final int PERIODIC = 0; public class ClockID { long time; long interval; int type; int status; public ClockID (long time, long interval, int type) { this.time = time; this.interval = interval; this.type = type; } public long getTime() { return time; } public WaitStatus waitID() { WaitStatus res; res = waitFunc (this); if (type == PERIODIC) time += interval; return res; } public void unschedule() { unscheduleFunc(this); } } public Clock() { adjust = 0; lastTime = 0; } protected synchronized long adjust(long internal) { long ret; ret = internal + adjust; /* make sure the time is increasing, else return last_time */ if (ret < lastTime) { ret = lastTime; } else { lastTime = ret; } return ret; } protected abstract long getInternalTime(); protected abstract WaitStatus waitFunc(ClockID id); protected abstract WaitStatus waitAsyncFunc(ClockID id); protected abstract void unscheduleFunc(ClockID id); public synchronized long getTime() { long internal, ret; internal = getInternalTime(); ret = adjust (internal); return ret; } public synchronized void setAdjust(long newAdjust) { adjust = newAdjust; } public synchronized long getAdjust() { return adjust; } public ClockID newSingleShotID(long time) { return new ClockID (time, 0, SINGLE); } public ClockID newPeriodicID(long time, long interval) { return new ClockID (time, interval, PERIODIC); } } cortado-0.6.0/src/com/fluendo/jst/ClockProvider.java100644 0 0 1564 11270111317 17511 0ustar 0 0 /* Cortado - a video player java applet * Copyright (C) 2004 Fluendo S.L. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. */ package com.fluendo.jst; public interface ClockProvider { public Clock provideClock(); } cortado-0.6.0/src/com/fluendo/jst/Element.java100644 0 0 25024 11270111317 16351 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.jst; import java.util.*; import com.fluendo.utils.*; public abstract class Element extends com.fluendo.jst.Object { public static final int FLAG_IS_SINK = (com.fluendo.jst.Object.OBJECT_FLAG_LAST << 1); public static final int ELEMENT_FLAG_LAST = (com.fluendo.jst.Object.OBJECT_FLAG_LAST << 16); protected Vector pads = new Vector(); protected java.lang.Object stateLock = new java.lang.Object(); private Vector padListeners = new Vector(); protected Clock clock; protected Bus bus; protected long baseTime; /* states */ public static final int NONE = 0; public static final int STOP = 1; public static final int PAUSE = 2; public static final int PLAY = 3; protected static String stateNames[] = { "none", "stop", "pause", "play" }; private static final int SHIFT = 4; private static final int MASK = 0xf; /* transition */ public static final int STOP_PAUSE = (STOP << SHIFT) | PAUSE; public static final int PAUSE_PLAY = (PAUSE << SHIFT) | PLAY; public static final int PLAY_PAUSE = (PLAY << SHIFT) | PAUSE; public static final int PAUSE_STOP = (PAUSE << SHIFT) | STOP; /* state return values */ public static final int FAILURE = 0; public static final int SUCCESS = 1; public static final int ASYNC = 2; public static final int NO_PREROLL = 3; public static String stateReturnNames[] = { "FAILURE", "SUCCESS", "ASYNC", "NO_PREROLL" }; /* current state, next and pending state */ protected int currentState; protected int nextState; protected int pendingState; protected int lastReturn; public static String getStateName(int state) { return stateNames[state]; } public static String getStateReturnName(int ret) { return stateReturnNames[ret]; } public String getMime () { return null; } public abstract String getFactoryName (); public int typeFind (byte[] data, int offset, int length) { return -1; } public Element() { this(null); } public Element(String name) { super (name); currentState = STOP; nextState = NONE; pendingState = NONE; lastReturn = SUCCESS; } public String toString () { return "Element: ["+getName()+"]"; } public synchronized void setClock (Clock newClock) { Debug.debug(this + ".setClock(" + newClock + ")"); clock = newClock; } public synchronized Clock getClock () { return clock; } public synchronized void setBus (Bus newBus) { bus = newBus; } public synchronized Bus getBus () { return bus; } public synchronized void addPadListener(PadListener listener) { padListeners.addElement (listener); } public synchronized void removePadListener(PadListener listener) { padListeners.removeElement (listener); } private synchronized void doPadListeners(int method, Pad pad) { for (Enumeration e = padListeners.elements(); e.hasMoreElements();) { PadListener listener = (PadListener) e.nextElement(); switch (method) { case 0: listener.padAdded (pad); break; case 1: listener.padRemoved (pad); break; case 2: listener.noMorePads (); break; } } } public synchronized Pad getPad(String name) { for (Enumeration e = pads.elements(); e.hasMoreElements();) { Pad pad = (Pad) e.nextElement(); if (name.equals(pad.getName())) return pad; } return null; } public synchronized boolean addPad(Pad newPad) { if (newPad.setParent (this) == false) return false; pads.addElement (newPad); doPadListeners (0, newPad); return true; } public synchronized boolean removePad(Pad aPad) { if (aPad.getParent() != this) return false; aPad.unParent(); pads.removeElement (aPad); doPadListeners (1, aPad); return true; } public synchronized void noMorePads() { doPadListeners (2, null); } public Enumeration enumPads() { return pads.elements(); } public void postMessage (Message message) { Bus myBus; synchronized (this) { myBus = bus; } if (myBus != null) myBus.post (message); } public synchronized int getState(int[] resState, int[] resPending, long timeout) { if (lastReturn == ASYNC) { if (pendingState != NONE) { long t; if (timeout == 0) t = 0; else if (timeout < 1000) t = 1; else t = timeout / 1000; try { wait (t); } catch (InterruptedException e) {} } } if (resState != null) resState[0] = currentState; if (resPending != null) resPending[0] = pendingState; return lastReturn; } private boolean padsActivate (boolean active) { int mode = (active ? Pad.MODE_PUSH : Pad.MODE_NONE); boolean res = true; for (Enumeration e = pads.elements(); e.hasMoreElements();) { Pad pad = (Pad) e.nextElement(); res &= pad.activate(mode); if (!res) return res; } return res; } public int getStateNext (int current, int pending) { int sign; sign = pending - current; if (sign > 0) sign = 1; else if (sign < 0) sign = -1; else sign = 0; return current + sign; } public int getTransition (int current, int next) { return (current << SHIFT) | next; } public int getTransitionCurrent (int transition) { return transition >> SHIFT; } public int getTransitionNext (int transition) { return transition & MASK; } public int continueState(int result) { int oldRet, oldState, oldNext; int current, next, pending; Message message = null; int transition = 0; synchronized (this) { oldRet = lastReturn; lastReturn = result; pending = pendingState; if (pending == NONE) return result; oldState = currentState; oldNext = nextState; current = currentState = oldNext; if (pending == current) { pendingState = NONE; nextState = NONE; transition = 0; if (oldState != oldNext || oldRet == ASYNC) { message = Message.newStateChanged (this, oldState, oldNext, pending); } } else { next = getStateNext (current, pending); transition = getTransition (current, next); nextState = next; lastReturn = ASYNC; message = Message.newStateChanged (this, oldState, oldNext, pending); } } if (message != null) postMessage (message); if (transition != 0) { result = doChangeState (transition); } else { synchronized (this) { notifyAll(); } } return result; } public synchronized void abortState() { if (pendingState != NONE && lastReturn != FAILURE) { lastReturn = FAILURE; notifyAll(); } } public void lostState() { boolean post = false; int current = 0; synchronized (this) { if (pendingState == NONE && lastReturn != FAILURE) { current = currentState; pendingState = nextState = currentState; lastReturn = ASYNC; post = true; } } if (post) { postMessage (Message.newStateChanged (this, current, current, current)); postMessage (Message.newStateDirty (this)); } } protected int changeState(int transition) { boolean res; int current, next; current = getTransitionCurrent (transition); next = getTransitionNext (transition); if (next == NONE || current == next) return lastReturn; switch (transition) { case STOP_PAUSE: res = padsActivate(true); break; case PAUSE_PLAY: res = true; break; case PLAY_PAUSE: res = true; break; case PAUSE_STOP: res = padsActivate(false); break; default: res = false; } if (res) return SUCCESS; else return FAILURE; } private int doChangeState(int transition) { int result; int current, next; current = getTransitionCurrent (transition); next = getTransitionNext (transition); result = changeState (transition); switch (result) { case FAILURE: abortState(); break; case SUCCESS: case NO_PREROLL: result = continueState(result); break; case ASYNC: if (current < next) { synchronized (this) { if (pendingState != NONE) { lastReturn = result; } } } else { result = continueState(SUCCESS); } break; } return result; } public final int setState(int newState) { int result; int transition; int oldPending; synchronized (stateLock) { synchronized (this) { if (lastReturn == FAILURE) { nextState = NONE; pendingState = NONE; lastReturn = SUCCESS; } oldPending = pendingState; pendingState = newState; if (oldPending != NONE) { /* upwards state change will happen ASYNC */ if (oldPending <= newState) { lastReturn = ASYNC; return ASYNC; } /* element is going to this state already */ else if (nextState == newState) { lastReturn = ASYNC; return ASYNC; } /* element was performing an ASYNC upward state change and * we request to go downward again. Start from the next pending * state then. */ else if (nextState > newState && lastReturn == ASYNC) { currentState = nextState; } } nextState = getStateNext (currentState, newState); transition = getTransition (currentState, nextState); } result = doChangeState (transition); } return result; } public boolean sendEvent (Event event) { return false; } public boolean query (Query query) { return false; } public Pad requestSinkPad(Pad peer) { return null; } } cortado-0.6.0/src/com/fluendo/jst/ElementFactory.java100644 0 0 11016 11275545213 17710 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.jst; import com.fluendo.utils.Debug; import java.util.Enumeration; import java.util.Vector; public class ElementFactory { private static String[] components = { "com.fluendo.plugin.HTTPSrc", "com.fluendo.plugin.VideoSink", "com.fluendo.plugin.AudioSinkJ2", "com.fluendo.plugin.AudioSinkSA", "com.fluendo.plugin.Queue", "com.fluendo.plugin.FakeSink", "com.fluendo.plugin.Overlay", "com.fluendo.plugin.Selector", "com.fluendo.plugin.OggDemux", "com.fluendo.plugin.TheoraDec", "com.fluendo.plugin.VorbisDec", "com.fluendo.plugin.KateDec", "com.fluendo.plugin.KateOverlay" }; private static Vector elements = new Vector(); static { loadElements(); } public static void loadElements() { try { for (int i = 0; i < components.length; ++i) { String str = components[i]; try { Class cl = Class.forName(str); Debug.log(Debug.INFO, "registered plugin: " + str); Element pl = (Element) cl.newInstance(); elements.addElement(pl); } catch (Throwable t) { Debug.log(Debug.INFO, "Failed to register plugin: " + str); } } } catch (Exception e) { e.printStackTrace(); } } private static final Element dup(Element element, String name) { Element result = null; Class cl = element.getClass(); try { result = (Element) cl.newInstance(); if (result != null && name != null) { result.setName(name); } Debug.log(Debug.INFO, "create element: " + result); } catch (Exception e) { e.printStackTrace(); } return result; } private static final Element findTypeFind(byte[] data, int offset, int length) { int best = -1; Element result = null; for (Enumeration e = elements.elements(); e.hasMoreElements();) { Element element = (Element) e.nextElement(); int rank = element.typeFind(data, offset, length); if (rank > best) { best = rank; result = element; } } return result; } public static final String typeFindMime(byte[] data, int offset, int length) { Element elem; String result = null; elem = findTypeFind(data, offset, length); if (elem != null) { result = elem.getMime(); } return result; } public static final Element makeTypeFind(byte[] data, int offset, int length, String name) { Element result = null; result = findTypeFind(data, offset, length); if (result != null) { result = dup(result, name); } return result; } public static final Element makeByMime(String mime, String name) { Element result = null; for (Enumeration e = elements.elements(); e.hasMoreElements();) { Element element = (Element) e.nextElement(); if (mime.equals(element.getMime())) { result = dup(element, name); break; } } return result; } public static final Element makeByName(String name, String elemName) { Element result = null; for (Enumeration e = elements.elements(); e.hasMoreElements();) { Element element = (Element) e.nextElement(); if (name.equals(element.getFactoryName())) { result = dup(element, elemName); break; } } return result; } } cortado-0.6.0/src/com/fluendo/jst/Event.java100644 0 0 5671 11270111317 16027 0ustar 0 0 /* Cortado - a video player java applet * Copyright (C) 2004 Fluendo S.L. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. */ package com.fluendo.jst; public class Event { /* types */ public static final int FLUSH_START = 1; public static final int FLUSH_STOP = 2; public static final int EOS = 3; public static final int NEWSEGMENT = 4; public static final int SEEK = 5; private static String typeNames[] = { "NULL", "FLUSH_START", "FLUSH_STOP", "EOS", "NEWSEGMENT", "SEEK" }; private int type; private int format; private boolean update; private long start; private long stop; private long position; private Event(int type) { position = -1; this.type = type; } public String toString() { String typeName = typeNames[type]; switch (type) { case SEEK: return "[Event] type: " + typeName + ", format: " + format + ", position: " + position; case NEWSEGMENT: return "[Event] type: " + typeName + ( update ? ", update" : ", non-update" ) + ", format: " + format + ", start: " + start + ", stop: " + stop + ", position: " + position; default: return "[Event] type: " + typeName; } } public int getType () { return type; } public static Event newEOS() { return new Event(EOS); } public static Event newFlushStart() { return new Event(FLUSH_START); } public static Event newFlushStop() { return new Event(FLUSH_STOP); } public static Event newSeek(int format, long position) { Event e = new Event(SEEK); e.format = format; e.position = position; return e; } public long parseSeekPosition () { return position; } public int parseSeekFormat () { return format; } public static Event newNewsegment(boolean update, int format, long start, long stop, long position) { Event e = new Event(NEWSEGMENT); e.update = update; e.format = format; e.start = start; e.stop = stop; e.position = position; return e; } public boolean parseNewsegmentUpdate () { return update; } public int parseNewsegmentFormat () { return format; } public long parseNewsegmentStart () { return start; } public long parseNewsegmentStop () { return stop; } public long parseNewsegmentPosition () { return position; } } cortado-0.6.0/src/com/fluendo/jst/Format.java100644 0 0 2223 11270111317 16164 0ustar 0 0 /* Cortado - a video player java applet * Copyright (C) 2004 Fluendo S.L. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. */ package com.fluendo.jst; public class Format { public static final int UNKNOWN = 0; public static final int DEFAULT = 1; public static final int BYTES = 2; public static final int TIME = 3; public static final int BUFFERS = 4; public static final int PERCENT = 5; public static final long PERCENT_MAX = 1000000; public static final long PERCENT_SCALE = 10000; } cortado-0.6.0/src/com/fluendo/jst/Message.java100644 0 0 13521 11270111317 16343 0ustar 0 0 /* Cortado - a video player java applet * Copyright (C) 2004 Fluendo S.L. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. */ package com.fluendo.jst; public class Message { /* types */ public static final int EOS = (1 << 0); public static final int ERROR = (1 << 1); public static final int WARNING = (1 << 2); public static final int INFO = (1 << 3); public static final int TAG = (1 << 4); public static final int BUFFERING = (1 << 5); public static final int STATE_CHANGED = (1 << 6); public static final int STATE_DIRTY = (1 << 7); public static final int STEP_DONE = (1 << 8); public static final int CLOCK_PROVIDE = (1 << 9); public static final int CLOCK_LOST = (1 << 10); public static final int NEW_CLOCK = (1 << 11); public static final int STRUCTURE_CHANGE = (1 << 12); public static final int STREAM_STATUS = (1 << 13); public static final int APPLICATION = (1 << 14); public static final int ELEMENT = (1 << 15); public static final int SEGMENT_START = (1 << 16); public static final int SEGMENT_DONE = (1 << 17); public static final int DURATION = (1 << 18); public static final int RESOURCE = (1 << 19); public static final int BYTEPOSITION = (1 << 20); private com.fluendo.jst.Object src; private int type; private boolean boolVal; private int intVal; private long longVal; private String stringVal; private int old, next, pending; private Message(com.fluendo.jst.Object src, int type) { this.src = src; this.type = type; } public com.fluendo.jst.Object getSrc () { return src; } public int getType () { return type; } public String toString () { switch (type) { case EOS: return "[Message]: "+src+" type: EOS"; case BUFFERING: return "[Message]: "+src+" type: BUFFERING, busy:"+boolVal+", percent:"+intVal; case STATE_CHANGED: return "[Message]: "+src+" type: STATE_CHANGED, old: " + Element.getStateName(old) + ", next: " + Element.getStateName(next)+ ", pending: " + Element.getStateName(pending); case STATE_DIRTY: return "[Message]: "+src+" type: STATE_DIRTY"; case STREAM_STATUS: return "[Message]: "+src+" type: STREAM_STATUS, "+(boolVal?"start":"stop")+", reason: "+ Pad.getFlowName(intVal)+", "+stringVal; case ERROR: return "[Message]: "+src+" type: ERROR, "+stringVal; default: return "[Message]: "+src+" type: "+type; } } public static Message newEOS(com.fluendo.jst.Object src) { return new Message(src, EOS); } public static Message newError(com.fluendo.jst.Object src, String str) { Message msg; msg = new Message(src, ERROR); msg.stringVal = str; return msg; } public static Message newWarning(com.fluendo.jst.Object src, String str) { Message msg; msg = new Message(src, WARNING); msg.stringVal = str; return msg; } public String parseErrorString() { return stringVal; } public static Message newBuffering(com.fluendo.jst.Object src, boolean busy, int percent) { Message msg; msg = new Message(src, BUFFERING); msg.boolVal = busy; msg.intVal = percent; return msg; } public boolean parseBufferingBusy() { return boolVal; } public int parseBufferingPercent() { return intVal; } public static Message newStateChanged(com.fluendo.jst.Object src, int old, int next, int pending) { Message msg = new Message(src, STATE_CHANGED); msg.old = old; msg.next = next; msg.pending = pending; return msg; } public int parseStateChangedOld() { return old; } public int parseStateChangedNext() { return next; } public int parseStateChangedPending() { return pending; } public static Message newStateDirty(com.fluendo.jst.Object src) { return new Message(src, STATE_DIRTY); } public static Message newStreamStatus(com.fluendo.jst.Object src, boolean start, int reason, String aString) { Message msg = new Message(src, STREAM_STATUS); msg.stringVal = aString; msg.boolVal = start; msg.intVal = reason; return msg; } public String parseStreamStatusString() { return stringVal; } public boolean parseStreamStatusStart() { return boolVal; } public int parseStreamStatusReason() { return intVal; } public static Message newResource(com.fluendo.jst.Object src, String aString) { Message msg = new Message(src, RESOURCE); msg.stringVal = aString; return msg; } public String parseResourceString() { return stringVal; } public static Message newDuration(com.fluendo.jst.Object src, int aFmt, long aDur) { Message msg = new Message(src, DURATION); msg.intVal = aFmt; msg.longVal = aDur; return msg; } public int parseDurationFormat() { return intVal; } public long parseDurationValue() { return longVal; } public static Message newBytePosition(com.fluendo.jst.Object src, long aPos) { Message msg = new Message(src, BYTEPOSITION); msg.longVal = aPos; return msg; } public long parseBytePosition() { return longVal; } } cortado-0.6.0/src/com/fluendo/jst/Object.java100644 0 0 3764 11270111317 16155 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.jst; public abstract class Object { protected String name; protected com.fluendo.jst.Object parent; protected int flags; public static final int OBJECT_FLAG_LAST = (1 << 4); public synchronized String getName () { return name; } public synchronized void setName (String newName) { name = newName; } public Object() { this("unnamed"); } public Object(String name) { super(); this.name = name; parent = null; } public synchronized boolean setParent (com.fluendo.jst.Object newParent) { if (parent != null) return false; parent = newParent; return true; } public synchronized com.fluendo.jst.Object getParent () { return parent; } public synchronized void unParent () { parent = null; } public synchronized void setFlag(int flag) { flags |= flag; } public synchronized void unsetFlag(int flag) { flags &= ~flag; } public synchronized boolean isFlagSet(int flag) { return (flags & flag) == flag; } public synchronized boolean setProperty(String name, java.lang.Object value) { return false; } public synchronized java.lang.Object getProperty(String name) { return null; } } cortado-0.6.0/src/com/fluendo/jst/Pad.java100644 0 0 20264 11270111317 15465 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.jst; import java.util.*; import com.fluendo.utils.*; public class Pad extends com.fluendo.jst.Object implements Runnable { /* pad directions */ public static final int UNKNOWN = 0; public static final int SRC = 1; public static final int SINK = 2; /* flow return values */ public static final int OK = 0; public static final int NOT_LINKED = -1; public static final int WRONG_STATE = -2; public static final int UNEXPECTED = -3; public static final int NOT_NEGOTIATED = -4; public static final int ERROR = -5; public static final int NOT_SUPPORTED = -6; /* modes */ public static final int MODE_NONE = 0; public static final int MODE_PUSH = 1; public static final int MODE_PULL = 2; protected Pad peer; protected int direction = UNKNOWN; protected boolean flushing; protected java.lang.Object streamLock = new java.lang.Object(); int mode; private Vector capsListeners = new Vector(); protected Caps caps; /* task stuff */ private static final int T_STOP = 0; private static final int T_PAUSE = 1; private static final int T_START = 2; private Thread thread; private int taskState; public static final boolean isFlowFatal (int ret) { return ret <= UNEXPECTED; } public static final boolean isFlowSuccess (int ret) { return ret >= OK; } public static final String getFlowName (int ret) { switch (ret) { case OK: return "ok"; case NOT_LINKED: return "not-linked"; case WRONG_STATE: return "wrong-state"; case UNEXPECTED: return "unexpected"; case NOT_NEGOTIATED: return "not-negotiated"; case ERROR: return "error"; case NOT_SUPPORTED: return "not-supported"; default: return "unknown"; } } public Pad(int direction) { this (direction, null); } public Pad(int direction, String name) { super(name); this.direction = direction; } public String toString () { String parentName; String thisName; if (parent != null) parentName = parent.getName(); else parentName = ""; thisName = getName(); if (thisName == null) thisName=""; //return "Pad: "+parentName+":"+thisName+" ["+super.toString()+"]"; return "Pad: "+parentName+":"+thisName; } public synchronized void addCapsListener(CapsListener listener) { capsListeners.addElement (listener); } public synchronized void removeCapsListener(CapsListener listener) { capsListeners.removeElement (listener); } private synchronized void doCapsListeners(Caps caps) { for (Enumeration e = capsListeners.elements(); e.hasMoreElements();) { CapsListener listener = (CapsListener) e.nextElement(); listener.capsChanged (caps); } } public synchronized boolean link (Pad newPeer) { /* already was connected */ if (peer != null) return false; /* wrong direction */ if (direction != SRC) return false; synchronized (newPeer) { if (newPeer.direction != SINK) return false; /* peer was connected */ if (newPeer.peer != null) return false; peer = newPeer; peer.peer = this; } return true; } public synchronized void unlink () { if (peer == null) return; if (direction == SRC) { peer.unlink (); } peer = null; } public synchronized Pad getPeer () { return peer; } protected boolean eventFunc (Event event) { boolean result; switch (event.getType()) { case Event.FLUSH_START: case Event.FLUSH_STOP: case Event.EOS: case Event.SEEK: case Event.NEWSEGMENT: default: result = false; break; } return result; } public final boolean sendEvent (Event event) { boolean result; Debug.debug(this + " got event " + event); switch (event.getType()) { case Event.FLUSH_START: setFlushing (true); result = eventFunc (event); break; case Event.FLUSH_STOP: synchronized (streamLock) { setFlushing (false); result = eventFunc (event); } break; case Event.NEWSEGMENT: case Event.EOS: synchronized (streamLock) { result = eventFunc (event); } break; case Event.SEEK: result = eventFunc (event); break; default: result = false; break; } return result; } public boolean query (Query query) { return false; } public synchronized Caps getCaps () { return this.caps; } protected boolean setCapsFunc (Caps caps) { return true; } public boolean setCaps (Caps caps) { boolean res = true; if (caps != null) res = setCapsFunc (caps); if (res) { this.caps = caps; if (caps != null) doCapsListeners (caps); } return res; } private final int chain (Buffer buffer) { synchronized (streamLock) { synchronized (this) { if (flushing) return WRONG_STATE; if (buffer.caps != null && buffer.caps != caps) { if (!setCaps(buffer.caps)) { buffer.free(); return NOT_NEGOTIATED; } } } int res = chainFunc(buffer); return res; } } protected int chainFunc (Buffer buffer) { return ERROR; } public final int push (Buffer buffer) { if (peer == null) { return NOT_LINKED; } return peer.chain (buffer); } public final boolean pushEvent (Event event) { if (peer == null) return false; return peer.sendEvent (event); } public synchronized void setFlushing (boolean flush) { flushing = flush; } public synchronized boolean isFlushing () { return flushing; } protected boolean activateFunc (int mode) { return true; } public final boolean activate (int newMode) { boolean res; Debug.debug(this + " activate mode = " + ( newMode == MODE_NONE ? "none" : "push" )); if (mode == newMode) return true; if (newMode == MODE_NONE) { setFlushing (true); } if ((res = activateFunc (newMode)) == false) return false; if (newMode != MODE_NONE) { setFlushing (false); } else { synchronized (streamLock) { setCaps (null); } } mode = newMode; return res; } protected void taskFunc() { } public void run() { synchronized (streamLock) { while (taskState != T_STOP) { while (taskState == T_PAUSE) { Debug.debug(parent.getName() + ":" + this.getName() + " paused, waiting..."); try { streamLock.wait(); } catch (InterruptedException ie) {} } if (taskState == T_STOP) break; try { taskFunc(); } catch (Throwable t) { t.printStackTrace(); } } } } public boolean startTask(String name) { synchronized (streamLock) { taskState = T_START; if (thread == null) { thread = new Thread(this, name); thread.start(); } streamLock.notifyAll(); } return true; } public boolean pauseTask() { taskState = T_PAUSE; synchronized (streamLock) { taskState = T_PAUSE; } return true; } public boolean stopTask() { Thread t; taskState = T_STOP; synchronized (streamLock) { taskState = T_STOP; streamLock.notifyAll(); t = thread; thread = null; } try { t.join(); } catch (InterruptedException ie) {} return true; } } cortado-0.6.0/src/com/fluendo/jst/PadListener.java100644 0 0 1701 11270111317 17146 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.jst; public interface PadListener { public void padAdded (Pad pad); public void padRemoved (Pad pad); public void noMorePads (); } cortado-0.6.0/src/com/fluendo/jst/Pipeline.java100644 0 0 32642 11270111317 16531 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.jst; import java.util.*; import com.fluendo.utils.*; public class Pipeline extends com.fluendo.jst.Element implements BusSyncHandler { protected Vector elements = new Vector(); protected Clock defClock; protected Clock fixedClock = null; protected Element clockProvider; protected Vector messages = new Vector(); protected Bus internalBus; private BusThread busThread; private StateThread stateThread; private boolean stateDirty = false; private boolean polling = false; protected long streamTime; private class BusThread extends Thread { private Bus bus; private boolean stopping; public BusThread (Bus bus) { super("cortado-BusThread-"+Debug.genId()); this.bus = bus; stopping = false; } public void run() { while (!stopping) { bus.waitAndDispatch (); } } public void shutDown() { stopping = true; bus.setFlushing(true); } } private class StateThread extends Thread { private boolean stopping; private boolean stateDirty; public StateThread () { super("cortado-StateThread-"+Debug.genId()); stopping = false; stateDirty = false; } public void run() { while (!stopping) { synchronized (this) { while (!stateDirty && !stopping) { try { wait(); } catch (InterruptedException e) {} } stateDirty = false; } if (!stopping) { synchronized (stateLock) { reCalcState(false); } } } } public synchronized void stateDirty() { stateDirty = true; notifyAll (); } public synchronized void shutDown() { stopping = true; notifyAll (); } } public Pipeline() { this (null); } public String getFactoryName () { return "pipeline"; } public Pipeline(String name) { super (name); defClock = new SystemClock(); clockProvider = null; internalBus = new Bus(); internalBus.setSyncHandler (this); bus = new Bus(); busThread = new BusThread(bus); busThread.start(); stateThread = new StateThread(); stateThread.start(); } public synchronized void shutDown() { if (stateThread != null) { stateThread.shutDown(); stateThread = null; } if (busThread != null) { busThread.shutDown(); busThread = null; } } public void useClock(Clock clock) { fixedClock = clock; } public boolean add(Element elem) { if (elem == null) return false; if (elem instanceof ClockProvider) { defClock = ((ClockProvider)elem).provideClock(); clockProvider = elem; } elements.addElement (elem); elem.baseTime = baseTime; elem.setBus (internalBus); return true; } public boolean remove(Element elem) { boolean res; if (elem == null) return false; if ((res = elements.removeElement (elem))) { if (elem == clockProvider) { defClock = new SystemClock(); clockProvider = null; } elem.setBus (null); elem.setClock (null); synchronized (this) { stateDirty = true; } } return res; } public Enumeration enumElements() { return elements.elements(); } private class SortedEnumerator implements Enumeration { private Vector queue; private Hashtable hash; private java.lang.Object next; private int mode; private void addToQueue (Element elem) { queue.addElement (elem); hash.put (elem, new Integer(-1)); } private void updateDegree (Element elem) { for (Enumeration p = elem.enumPads(); p.hasMoreElements();) { Pad pad = (Pad) p.nextElement(); if (pad.direction == Pad.SINK) { Pad peer; Element peerParent; int oldDeg, newDeg; peer = pad.peer; if (peer == null) continue; peerParent = (Element) peer.parent; if (peerParent == null) continue; oldDeg = ((Integer)hash.get (peerParent)).intValue(); newDeg = oldDeg + mode; if (newDeg == 0) { addToQueue (peerParent); } else { hash.put (peerParent, new Integer (newDeg)); } } } } public SortedEnumerator() { queue = new Vector(); hash = new Hashtable(); /* reset all degrees, add sinks to queue */ for (Enumeration e = enumElements(); e.hasMoreElements();) { Element elem = (Element) e.nextElement(); if (elem.isFlagSet (Element.FLAG_IS_SINK)) { addToQueue (elem); } else { hash.put (elem, new Integer(0)); } } mode = 1; /* update all degrees */ for (Enumeration e = enumElements(); e.hasMoreElements();) { updateDegree ((Element) e.nextElement()); } mode = -1; queueNextElement(); } private void queueNextElement () { if (queue.isEmpty()) { int bestDeg = Integer.MAX_VALUE; Element bestElem = null; for (Enumeration e = enumElements(); e.hasMoreElements();) { Element elem = (Element) e.nextElement(); int deg; deg = ((Integer)hash.get (elem)).intValue(); if (deg < 0) continue; if (bestElem == null || bestDeg > deg) { bestElem = elem; bestDeg = deg; } } if (bestElem != null) { if (bestDeg != 0) { System.out.println (this+" loop detected in pipeline!!"); } next = bestElem; hash.put (next, new Integer(-1)); } else { next = null; } } else { next = queue.elementAt (0); queue.removeElementAt (0); } if (next != null) updateDegree ((Element) next); } public boolean hasMoreElements() { return next != null; } public java.lang.Object nextElement() throws NoSuchElementException { java.lang.Object result = next; if (result == null) throw new NoSuchElementException(); queueNextElement (); return result; } } public Enumeration enumSorted() { return new SortedEnumerator(); } private class SinkEnumerator implements Enumeration { private Enumeration e; private java.lang.Object next; public SinkEnumerator() { e = enumElements(); queueNextElement(); } private void queueNextElement() { next = null; while (e.hasMoreElements()) { Element elem = (Element) e.nextElement(); if (elem.isFlagSet (Element.FLAG_IS_SINK)) { next = elem; break; } } } public boolean hasMoreElements() { return next != null; } public java.lang.Object nextElement() throws NoSuchElementException { java.lang.Object result = next; if (result == null) throw new NoSuchElementException(); queueNextElement (); return result; } } public Enumeration enumSinks() { return new SinkEnumerator(); } private void replaceMessage (Message message, int type) { int len = messages.size(); Message msg; com.fluendo.jst.Object src = message.getSrc(); for (int i=0; i>> PRE-SEGMENT DROP" ); buf.free(); return OK; } else { lastTime = time - segStart + segPosition; } } buf.setFlag (com.fluendo.jst.Buffer.FLAG_DISCONT, discont); discont = false; if ((res = finishPreroll(buf)) != Pad.OK) { Debug.debug(parent.getName() + " " + time + " >>> PREROLL DROP" ); return res; } Debug.debug(parent.getName() + " sync " + time ); status = doSync(time); switch (status.status) { case WaitStatus.LATE: if (maxLateness != -1 && status.jitter > maxLateness) { Debug.debug(parent.getName() + " " + time + " >>> LATE, DROPPED" ); break; } // Not too late, fall through... case WaitStatus.OK: try { Debug.debug(parent.getName() + " >>> " + time); res = render (buf); } catch (Throwable t) { postMessage (Message.newError (this, "render exception: "+t.getMessage())); res = Pad.ERROR; } break; default: Debug.debug(parent.getName() + " " + time + " >>> SYNC DROP" ); res = Pad.OK; break; } buf.free(); return res; } protected boolean setCapsFunc (Caps caps) { boolean res; Sink sink = (Sink) parent; res = sink.setCapsFunc (caps); return res; } protected boolean activateFunc (int mode) { if (mode == MODE_NONE) { synchronized (prerollLock) { if (havePreroll) { prerollLock.notify(); } needPreroll = false; havePreroll = false; this.flushing = true; } isEOS = false; } else { this.flushing = false; } return true; } }; protected int preroll (Buffer buf) { return Pad.OK; } protected boolean doEvent(Event event) { return true; } protected WaitStatus doSync(long time) { WaitStatus ret = new WaitStatus(); Clock.ClockID id = null; synchronized (this) { if (flushing) { ret.status = WaitStatus.UNSCHEDULED; return ret; } if (time == -1) { ret.status = WaitStatus.OK; return ret; } time = time - segStart + baseTime; if (clock != null) id = clockID = clock.newSingleShotID (time); } if (id != null) { ret = id.waitID(); } else ret.status = WaitStatus.OK; synchronized (this) { clockID = null; } return ret; } protected boolean setCapsFunc (Caps caps) { return true; } protected int render (Buffer buf) { return Pad.OK; } public Sink () { super (); addPad (sinkpad); setFlag (Element.FLAG_IS_SINK); } public boolean sendEvent (Event event) { return sinkpad.pushEvent (event); } public boolean query (Query query) { switch (query.getType()) { case Query.DURATION: return sinkpad.getPeer().query (query); case Query.POSITION: { long position = -1; if (query.parsePositionFormat() == Format.TIME) { synchronized (this) { if (currentState == PLAY) { if (clock != null) { position = clock.getTime() - baseTime + segPosition + segStart; } } else { position = pauseTime + segPosition + segStart; } } query.setPosition(Format.TIME, position); } else { return sinkpad.getPeer().query (query); } break; } default: return sinkpad.getPeer().query (query); } return true; } protected int changeState (int transition) { int result = SUCCESS; int presult; switch (transition) { case STOP_PAUSE: this.isEOS = false; synchronized (prerollLock) { needPreroll = true; havePreroll = false; } result = ASYNC; break; case PAUSE_PLAY: synchronized (prerollLock) { if (havePreroll) { needPreroll = false; prerollLock.notify(); } else { needPreroll = false; } } break; case PLAY_PAUSE: synchronized (this) { pauseTime = clock.getTime() - baseTime; } break; default: break; } presult = super.changeState(transition); if (presult == FAILURE) { Debug.debug(this+" super state change failed"); return presult; } switch (transition) { case PLAY_PAUSE: { boolean checkEOS; Debug.debug(this+" play->paused"); /* unlock clock */ synchronized (this) { if (clockID != null) { Debug.debug(this+" unschedule clockID: "+ clockID); clockID.unschedule(); } checkEOS = this.isEOS; Debug.debug(this+" checkEOS: "+ checkEOS); } synchronized (prerollLock) { Debug.debug(this+" havePreroll: "+ havePreroll); if (!havePreroll && !checkEOS && pendingState == PAUSE) { needPreroll = true; result = ASYNC; } } break; } case PAUSE_STOP: break; default: break; } return result; } public synchronized boolean setProperty(String name, java.lang.Object value) { boolean res = true; if (name.equals("max-lateness")) { maxLateness = Long.parseLong((String)value); } else { res = false; } return res; } } cortado-0.6.0/src/com/fluendo/jst/SourceInfo.java100644 0 0 230 11350743266 17001 0ustar 0 0 package com.fluendo.jst; public class SourceInfo { public String revision = "0.6.0"; public String branch = "Xiph"; public SourceInfo() { } } cortado-0.6.0/src/com/fluendo/jst/SystemClock.java100644 0 0 4330 11274362076 17213 0ustar 0 0 /* Cortado - a video player java applet * Copyright (C) 2004 Fluendo S.L. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. */ package com.fluendo.jst; import com.fluendo.utils.*; public class SystemClock extends Clock { protected long getInternalTime() { return System.currentTimeMillis() * Clock.MSECOND; } protected WaitStatus waitFunc(ClockID id) { WaitStatus res = new WaitStatus(); long real = getInternalTime(); long entryt = id.time; long now = adjust (real); res.jitter = now - entryt; if (res.jitter < 0) { Debug.log(Debug.DEBUG, "Waiting from "+now+" until "+entryt+" ("+(-res.jitter)+"us)"); long millis; int nanos; millis = -res.jitter / Clock.MSECOND; nanos = (int) ((-res.jitter % Clock.MSECOND) * Clock.MSECOND); synchronized (this) { if (id.status == WaitStatus.UNSCHEDULED) { res.status = WaitStatus.UNSCHEDULED; return res; } id.status = WaitStatus.OK; try { wait (millis, nanos); } catch (InterruptedException e) {} } res.status = id.status; } else if (res.jitter == 0) { res.status = WaitStatus.OK; } else { Debug.log(Debug.DEBUG, "Wait for timestamp " + now + " is late by " + res.jitter + "us"); res.status = WaitStatus.LATE; } return res; } protected WaitStatus waitAsyncFunc(ClockID id) { return WaitStatus.newOK(); } protected void unscheduleFunc(ClockID id) { synchronized (this) { id.status = WaitStatus.UNSCHEDULED; notifyAll(); } } } cortado-0.6.0/src/com/fluendo/jst/WaitStatus.java100644 0 0 1151 11270111317 17043 0ustar 0 0 package com.fluendo.jst; public class WaitStatus { int status; long jitter; public static final int OK = 0; public static final int LATE = 1; public static final int UNSCHEDULED = 2; public static final int BUSY = 3; public static final int BADTIME = 4; public static final int ERROR = 5; public static final int UNSUPPORTED = 6; WaitStatus(int status_, long jitter_) { status = status_; jitter = jitter_; } WaitStatus() { status = ERROR; jitter = 0; } public static WaitStatus newOK() { return new WaitStatus(OK, 0); } } cortado-0.6.0/src/com/fluendo/jtiger/BasicTextRenderer.java100644 0 0 3212 11350725171 21004 0ustar 0 0 /* JTiger * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JTiger are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jtiger; import java.awt.*; class BasicTextRenderer implements TextRenderer { public void renderText(Graphics g, Rectangle region, Font font, String text) { g.setFont(font); FontMetrics fm = g.getFontMetrics(); int tw = fm.stringWidth(text); // int shadow_dx = (int)(Math.max(font_size * 0.075f, 2)+0.5f), shadow_dy = (int)(Math.max(font_size * 0.075f, 2)+0.5f); int shadow_dx=1,shadow_dy=1; int tx = region.x+(region.width-tw)/2; int ty = region.y; g.setColor(Color.black); g.drawString(text, tx+shadow_dx, ty); g.drawString(text, tx-shadow_dx, ty); g.drawString(text, tx, ty-shadow_dy); g.drawString(text, tx, ty+shadow_dy); g.setColor(Color.white); g.drawString(text, tx, ty); } } cortado-0.6.0/src/com/fluendo/jtiger/FancyTextRenderer.java100644 0 0 5022 11350725171 21024 0ustar 0 0 /* JTiger * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JTiger are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jtiger; import java.awt.*; import com.fluendo.utils.*; import java.text.*; import java.awt.font.*; class FancyTextRenderer implements TextRenderer { public void renderText(Graphics g, Rectangle region, Font font, String text) { /* This path uses API calls that were not present in Java 1.1 */ Graphics2D g2 = (Graphics2D)g; g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); AttributedString atext = new AttributedString(text, font.getAttributes()); AttributedCharacterIterator text_it = atext.getIterator(); int text_end = text_it.getEndIndex(); FontRenderContext frc = g2.getFontRenderContext(); LineBreakMeasurer lbm = new LineBreakMeasurer(text_it, frc); float dy = 0.0f; //float shadow_dx = Math.max(font_size * 0.075f, 1.0f), shadow_dy = Math.max(font_size * 0.075f, 1.0f); //int shadow_dx = (int)(Math.max(font_size * 0.075f, 2)+0.5f), shadow_dy = (int)(Math.max(font_size * 0.075f, 2)+0.5f); int shadow_dx=1,shadow_dy=1; while (lbm.getPosition() < text_end) { TextLayout layout = lbm.nextLayout(region.width); dy += layout.getAscent(); float tw = layout.getAdvance(); float tx = region.x+((region.width-tw)/2); g2.setColor(Color.black); layout.draw(g2, tx+shadow_dx, region.y+dy); layout.draw(g2, tx-shadow_dx, region.y+dy); layout.draw(g2, tx, region.y+dy-shadow_dy); layout.draw(g2, tx, region.y+dy+shadow_dy); g2.setColor(Color.white); layout.draw(g2, tx, region.y+dy); dy += layout.getDescent() + layout.getLeading(); } } } cortado-0.6.0/src/com/fluendo/jtiger/Item.java100644 0 0 13400 11350725171 16345 0ustar 0 0 /* JTiger * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JTiger are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jtiger; import java.awt.*; import com.fluendo.jkate.Tracker; import com.fluendo.utils.*; public class Item { private Tracker kin = null; private boolean alive = false; private Font font = null; private int font_size = 0; private String text = null; private TigerBitmap background_image = null; private int width = -1; private int height = -1; private Rectangle region = new Rectangle(); private boolean dirty = true; private static TextRenderer textRenderer = detectTextRenderer(); private static TextRenderer detectTextRenderer() { TextRenderer tr = null; try { Class c = Class.forName("com.fluendo.jtiger.BasicTextRenderer"); tr = (TextRenderer)c.newInstance(); Debug.info("jtiger.Item: detecting Graphics2D"); Class.forName("java.awt.Graphics2D"); Debug.info("jtiger.Item: detecting TextLayout"); Class.forName("java.awt.font.TextLayout"); Debug.info("jtiger.Item: detecting AttributedString"); Class.forName("java.text.AttributedString"); c = Class.forName("com.fluendo.jtiger.FancyTextRenderer"); tr = (TextRenderer)c.newInstance(); Debug.info("jtiger.Item: We can use the fancy text renderer"); } catch (Throwable e) { if (tr == null) { Debug.info("jtiger.Item: We cannot use any text renderer: "+e.toString()); } else { Debug.info("jtiger.Item: We have to use the basic text renderer: "+e.toString()); } } return tr; } /** * Create a new item from a Kate event. */ public Item(com.fluendo.jkate.Event ev) { this.kin = new Tracker(ev); text = null; if (ev.text != null && ev.text.length > 0) { try { text = new String(ev.text, "UTF8"); } catch (Exception e) { Debug.warning("Failed to convert text from UTF-8 - text will not display"); text = null; } } dirty = false; /* not dirty yet, inactive */ } /** * Create a font suitable for displaying on the given component */ protected void createFont(Component c, Image img) { font_size = img.getWidth(null) / 32; if (font_size < 12) font_size = 12; font = new Font("sansserif", Font.BOLD, font_size); // TODO: should be selectable ? } /** * Regenerate any cached data to match any relevant changes in the * given component */ protected void updateCachedData(Component c, Image img) { int img_width = img.getWidth(null); int img_height = img.getHeight(null); if (img_width == width && img_height == height) return; createFont(c, img); width = img_width; height = img_height; dirty = true; } /** * Updates the item at the given time. * returns true for alive, false for dead */ public boolean update(Component c, Dimension d, double t) { com.fluendo.jkate.Event ev = kin.ev; if (ev == null) return false; /* early out if we're not within the lifetime of the event */ if (t < ev.start_time) return true; if (t >= ev.end_time) { alive = false; dirty = true; return false; /* we're done, and will get destroyed */ } if (!alive) { alive = true; dirty = true; } return kin.update(t-ev.start_time, d, d); } /** * Set up the region. */ public void setupRegion(Component c, Image img) { if (kin.has[Tracker.has_region]) { region.x = (int)(kin.region_x + 0.5f); region.y = (int)(kin.region_y + 0.5f); region.width = (int)(kin.region_w + 0.5f); region.height = (int)(kin.region_h + 0.5f); } else { Dimension d = new Dimension(img.getWidth(null), img.getHeight(null)); region.x = (int)(d.width * 0.1f + 0.5f); region.y = (int)(d.height * 0.8f + 0.5f); region.width = (int)(d.width * 0.8f + 0.5f); region.height = (int)(d.height * 0.1f + 0.5f); } } /** * Renders the item on the given image. */ public void render(Component c, Image img) { if (!alive) return; updateCachedData(c, img); setupRegion(c, img); renderBackground(c, img); renderText(img); dirty = false; } /** * Render a background for the item, if approrpiate. * The background may be a color, or an image. */ public void renderBackground(Component c, Image img) { if (kin.ev.bitmap != null) { if (background_image == null) { background_image = new TigerBitmap(c, kin.ev.bitmap, kin.ev.palette); } Graphics g = img.getGraphics(); g.drawImage(background_image.getScaled(region.width, region.height), region.x, region.y, null); g.dispose(); } } /** * Render text text for the item, if approrpiate. */ public void renderText(Image img) { if (text == null) return; Graphics g = img.getGraphics(); if (textRenderer != null) textRenderer.renderText(g, region, font, text); g.dispose(); } public boolean isDirty() { return dirty; } } cortado-0.6.0/src/com/fluendo/jtiger/Renderer.java100644 0 0 4640 11350725171 17203 0ustar 0 0 /* JTiger * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JTiger are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jtiger; import java.util.*; import java.awt.*; public class Renderer { private Vector items = new Vector(); private boolean dirty = true; /** * Add a new event to the renderer. */ public void add(com.fluendo.jkate.Event ev) { items.addElement(new Item(ev)); dirty = true; } /** * Update the renderer, and all the events it tracks. * Returns 1 if there is nothing to draw, as an optimization */ public int update(Component c, Dimension d, double t) { for (int n=0; n * * Parts of JTiger are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jtiger; import java.awt.*; interface TextRenderer { public void renderText(Graphics g, Rectangle region, Font font, String text); } cortado-0.6.0/src/com/fluendo/jtiger/TigerBitmap.java100644 0 0 5477 11335602774 17663 0ustar 0 0 /* JTiger * Copyright (C) 2008 ogg.k.ogg.k * * Parts of JTiger are based on code by Wim Taymans * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.fluendo.jtiger; import java.awt.*; import java.awt.image.*; import com.fluendo.jkate.*; import com.fluendo.utils.*; public class TigerBitmap { private Image image; private Image scaled_image; /** * Create a new TigerBitmap from a Kate bitmap and optional palette. */ public TigerBitmap(Component c, Bitmap kb, Palette kp) { if (kb == null) { image = null; } else if (kb.bpp == 0) { /* PNG */ image = createPNGBitmap(c, kb, kp); } else { if (kp == null) { image = null; } else { image = createPalettedBitmap(c, kb, kp); } } if (image == null) { // if we failed to create the bitmap, replace it with a 1x1 transparent one to avoid corner cases image = c.getToolkit().createImage(new MemoryImageSource(1, 1, new int[]{0}, 0, 1)); } } /** * Returns a scaled version of the image. */ public Image getScaled(int width, int height) { if (scaled_image == null || width != scaled_image.getWidth(null) || height != scaled_image.getHeight(null)) { scaled_image = image.getScaledInstance(width, height, Image.SCALE_SMOOTH); // TODO: quality setting } return scaled_image; } /** * Create an image from bits representing a PNG image. */ private Image createPNGBitmap(Component c, Bitmap kb, Palette kp) { Debug.warning("PNG bitmaps not supported yet"); return null; } /** * Create a paletted image. */ private Image createPalettedBitmap(Component c, Bitmap kb, Palette kp) { byte[] cmap = new byte[4*kp.colors.length]; for (int n=0; n= 0) ? urlString : base + "/" + urlString; Debug.log(Debug.INFO, "trying to determine duration for " + docurlstring); URL url = new URL(docurlstring); duration = durationParam = new DurationScanner().getDurationForURL(url, userId, password); Debug.log(Debug.INFO, "Determined stream duration to be approx. " + durationParam); } catch (Exception ex) { Debug.log(Debug.WARNING, "Couldn't determine duration for stream."); } } status.setDuration(durationParam); inStatus = false; mayHide = (hideTimeout == 0); hideCounter = 0; if (showStatus != STATUS_HIDE) { status.setVisible(true); } else { status.setVisible(false); } createMenu(); } public void createMenu() { subtitlesMenu = new Menu("Subtitles"); subtitlesMenu.addActionListener(this); menu = new PopupMenu(); menu.add(subtitlesMenu); menu.addSeparator(); menu.add("About..."); menu.addActionListener(this); this.add(menu); populateMenu(subtitlesMenu); } public String getCategoryName(String code) { String names[]={ "CC", "closed captions", "SUB", "subtitles", "TAD", "text audio descriptions", "KTV", "karaoke", "TIK", "ticker text", "AR", "active regions", "NB", "semantic annotations", "META","metadata", "TRX", "transcript", "LRC", "lyrics", "LIN", "linguistic markup", "CUE", "cue points", "subtitles", "subtitles", "spu-subtitles", "subtitles (images)", "lyrics", "lyrics", "K-SPU", "subtitles (images)", }; for (int n=0;n= 0) { String language = rfc3066.substring(0, sep); String country = rfc3066.substring(sep+1); return new Locale(language, country); } else { return new Locale(rfc3066,""); } } public void populateMenu(Menu subtitlesMenu) { subtitlesMenu.removeAll(); int nstreams = pipeline.getNumKateStreams(); if (nstreams > 0) { subtitlesMenu.enable(); subtitlesMenu.add("Off"); subtitlesMenu.addSeparator(); for (int n=0; n= 1 && idx <= pipeline.getNumKateStreams()) { String sidx = new String(""+(idx-1)); Debug.log(Debug.WARNING, "Switching to subtitles stream "+sidx); setParam("kateIndex",sidx); setParam("kateLanguage",""); setParam("kateCategory",""); pipeline.enableKateStream(idx+1, "", ""); } else { Debug.log(Debug.WARNING, "Failed to parse subtitle selection command string: "+command); } } } public Graphics getGraphics() { Dimension dim = getSize(); Graphics g = super.getGraphics(); if (status != null && status.isVisible()) { g.setClip(0, 0, dim.width, dim.height - statusHeight); } else { g.setClip(0, 0, dim.width, dim.height); } return g; } public void componentHidden(ComponentEvent e) { } public void componentMoved(ComponentEvent e) { } public void componentResized(ComponentEvent e) { /* reset cached dimension */ appletDimension = super.getSize(); if (pipeline != null) { pipeline.resize(appletDimension); } } public void componentShown(ComponentEvent e) { // reset cached dimension appletDimension = super.getSize(); Debug.debug("Component shown, size = " + appletDimension); if (pipeline != null) { pipeline.resize(appletDimension); } } public Dimension getSize() { if (appletDimension == null) { appletDimension = super.getSize(); } return appletDimension; } public void update(Graphics g) { paint(g); } public void run() { try { realRun(); } catch (Throwable t) { shutDown(t); } } private void realRun() { Debug.log(Debug.INFO, "entering status thread"); while (statusRunning) { try { long now; if (_currentTime != currentTime && currentTime >= 0 && duration > currentTime) { doSeek(currentTime / duration); } currentTime = _currentTime = (double) pipeline.getPosition() / Clock.SECOND; now = pipeline.getPosition() / Clock.SECOND; status.setTime(now); Thread.sleep(1000); if (hideCounter > 0) { hideCounter--; if (hideCounter == 0) { mayHide = true; setStatusVisible(false, false); } } // we want to be able to change subtitles at runtime without having // to restart the player, and selecting a stream which is already selected // is very cheap, so we update the stream to play periodically. pipeline.enableKateStream( Integer.valueOf(getParam("kateIndex", "" + -1)).intValue(), getParam("kateLanguage", ""), getParam("kateCategory", "") ); } catch (Exception e) { if (statusRunning) { Debug.log(Debug.ERROR, "Exception in status thread:"); e.printStackTrace(); } } } Debug.log(Debug.INFO, "exit status thread"); } public void paint(Graphics g) { Dimension dim = getSize(); int dwidth = dim.width; int dheight = dim.height; /* sometimes dimension is wrong */ if (dwidth <= 0 || dheight < statusHeight) { appletDimension = null; Debug.log(Debug.WARNING, "paint aborted: appletDimension wrong; dwidth " + dwidth + ", dheight " + dheight + ", statusHeight " + statusHeight); return; } if (status != null) { status.setBounds(0, dheight - statusHeight, dwidth, statusHeight); status.paint(g); } } private void setStatusVisible(boolean b, boolean force) { /* no change, do nothing */ if (status.isVisible() == b) { return; } /* refuse to hide when hideTimeout did not expire */ if (!b && !mayHide) { return; } if (!force) { if (showStatus == STATUS_SHOW && !b) { return; } if (showStatus == STATUS_HIDE && b) { return; } } /* never hide when we are in error */ if (isError && !b) { return; } /* don't make invisible when the mouse pointer is inside status area */ if (inStatus && !b) { b = true; } if (b != status.isVisible()) { Debug.log(Debug.INFO, "Status: " + (b ? "Show" : "Hide")); } if (b) { hideCounter = hideTimeout; } status.setVisible(b); repaint(); } private boolean intersectStatus(MouseEvent e) { int y = e.getY(); int max = getSize().height; int top = max - statusHeight; inStatus = y > top && y < max; return inStatus; } public void mouseClicked(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { inStatus = false; } public void mousePressed(MouseEvent e) { if (intersectStatus(e)) { int y = getSize().height - statusHeight; e.translatePoint(0, -y); ((MouseListener) status).mousePressed(e); } else { if ((e.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK) { populateMenu(subtitlesMenu); menu.show(this, e.getX(), e.getY()); } } } public void mouseReleased(MouseEvent e) { if (intersectStatus(e)) { int y = getSize().height - statusHeight; e.translatePoint(0, -y); ((MouseListener) status).mouseReleased(e); } else { status.cancelMouseOperation(); } } public void mouseDragged(MouseEvent e) { if (intersectStatus(e)) { int y = getSize().height - statusHeight; setStatusVisible(true, false); e.translatePoint(0, -y); ((MouseMotionListener) status).mouseDragged(e); } /*else { setStatusVisible(false, false); }*/ } public void mouseMoved(MouseEvent e) { if (intersectStatus(e)) { int y = getSize().height - statusHeight; setStatusVisible(true, false); e.translatePoint(0, -y); ((MouseMotionListener) status).mouseMoved(e); } /*else { setStatusVisible(false, false); }*/ setStatusVisible(true, false); } public void handleMessage(Message msg) { switch (msg.getType()) { case Message.WARNING: Debug.info(msg.toString()); break; case Message.ERROR: Debug.info(msg.toString()); if (!isError) { status.setMessage(msg.parseErrorString()); status.setState(Status.STATE_STOPPED); pipeline.setState(Element.STOP); setStatusVisible(true, true); isError = true; } break; case Message.EOS: Debug.log(Debug.INFO, "EOS: playback ended"); if (!isError) { status.setState(Status.STATE_STOPPED); status.setMessage("Playback ended"); isEOS = true; pipeline.setState(Element.STOP); setStatusVisible(true, false); } break; case Message.STREAM_STATUS: Debug.info(msg.toString()); break; case Message.RESOURCE: if (!isError) { status.setMessage(msg.parseResourceString()); setStatusVisible(true, false); } break; case Message.DURATION: long duration; duration = msg.parseDurationValue(); status.setByteDuration(duration); Debug.log(Debug.DEBUG, "got duration: " + duration); if (duration != -1) { /* we got duration, we can enable automatic setting */ if (seekable == BOOL_AUTO) { status.setSeekable(true); } if (live == BOOL_AUTO) { status.setLive(false); } } break; case Message.BUFFERING: boolean busy; int percent; if (isError) { break; } busy = msg.parseBufferingBusy(); percent = msg.parseBufferingPercent(); if (busy) { if (!isBuffering) { Debug.log(Debug.INFO, "PAUSE: we are buffering"); if (desiredState == Element.PLAY) { pipeline.setState(Element.PAUSE); } isBuffering = true; setStatusVisible(true, false); } status.setBufferPercent(busy, percent); } else { if (isBuffering) { Debug.log(Debug.INFO, "PLAY: we finished buffering"); if (desiredState == Element.PLAY) { pipeline.setState(Element.PLAY); } isBuffering = false; setStatusVisible(false, false); } status.setBufferPercent(busy, percent); } break; case Message.STATE_CHANGED: if (msg.getSrc() == pipeline) { int old, next; old = msg.parseStateChangedOld(); next = msg.parseStateChangedNext(); switch (next) { case Element.PAUSE: if (!isError && !isEOS) { status.setMessage("Paused"); } status.setState(Status.STATE_PAUSED); break; case Element.PLAY: if (!isError && !isEOS) { status.setMessage("Playing"); setStatusVisible(false, false); if (!mayHide) { hideCounter = hideTimeout; } } status.setState(Status.STATE_PLAYING); break; case Element.STOP: if (!isError && !isEOS) { status.setMessage("Stopped"); setStatusVisible(true, false); } status.setState(Status.STATE_STOPPED); break; } } break; case Message.BYTEPOSITION: status.setBytePosition(msg.parseBytePosition()); break; default: break; } } public void doPause() { isError = false; isEOS = false; paused = true; status.setMessage("Pause"); desiredState = Element.PAUSE; pipeline.setState(desiredState); } public void doPlay() { isError = false; isEOS = false; paused = false; status.setMessage("Play"); desiredState = Element.PLAY; pipeline.setState(desiredState); } public void doStop() { status.setMessage("Stop"); desiredState = Element.STOP; pipeline.setState(desiredState); } public void doSeek(double aPos) { boolean res; com.fluendo.jst.Event event; /* get value, convert to PERCENT and construct seek event */ event = com.fluendo.jst.Event.newSeek(Format.PERCENT, (int) (aPos * 100.0 * Format.PERCENT_SCALE)); /* send event to pipeline */ res = pipeline.sendEvent(event); if (!res) { Debug.log(Debug.WARNING, "seek failed"); } } public double getPlayPosition() { return (double) pipeline.getPosition() / Clock.SECOND; } public void onState(int aState) { switch (aState) { case Status.STATE_PAUSED: doPause(); break; case Status.STATE_PLAYING: doPlay(); break; case Status.STATE_STOPPED: doStop(); break; default: break; } } public void onSeek(double aPos) { doSeek(aPos); } public void onAudio() { // TODO } public void onSubtitles(int x, int y) { Dimension dim = getSize(); PopupMenu subtitlesPopupMenu = new PopupMenu(); populateMenu(subtitlesPopupMenu); subtitlesPopupMenu.addActionListener(this); this.add(subtitlesPopupMenu); subtitlesPopupMenu.show(this, x, y+dim.height-statusHeight); } public synchronized void start() { int res; Debug.info("Application starting"); addComponentListener(this); addMouseListener(this); addMouseMotionListener(this); status.addStatusListener(this); if (autoPlay) { desiredState = Element.PLAY; } else { desiredState = Element.PAUSE; } res = pipeline.setState(desiredState); if (statusThread != null) { throw new RuntimeException("invalid state"); } statusThread = new Thread(this, "cortado-StatusThread-" + Debug.genId()); statusRunning = true; statusThread.start(); } public synchronized void stop() { Debug.info("Application stopping..."); status.removeStatusListener(this); removeMouseMotionListener(this); removeMouseListener(this); removeComponentListener(this); statusRunning = false; desiredState = Element.STOP; if (pipeline != null) { try { pipeline.setState(desiredState); } catch (Throwable e) { } try { pipeline.shutDown(); } catch (Throwable e) { } pipeline = null; } if (statusThread != null) { try { statusThread.interrupt(); } catch (Throwable e) { } try { statusThread.join(); } catch (Throwable e) { } statusThread = null; } Debug.info("Application stopped"); } public int getStatusHeight() { return statusHeight; } public int getShowStatus() { return showStatus; } /* HTML-5 media element methods */ public synchronized void play() { doPlay(); } public synchronized void pause() { doPause(); } } /* dialog box */ class AppFrame extends Frame implements WindowListener { private static final long serialVersionUID = 1L; public AppFrame(String title) { super(title); addWindowListener(this); } public void windowClosing(WindowEvent e) { setVisible(false); dispose(); System.exit(0); } public void windowClosed(WindowEvent e) { } public void windowDeactivated(WindowEvent e) { } public void windowActivated(WindowEvent e) { } public void windowDeiconified(WindowEvent e) { } public void windowIconified(WindowEvent e) { } public void windowOpened(WindowEvent e) { } } class AboutFrame extends AppFrame { private static final long serialVersionUID = 1L; Dialog d; public String getRevision() { return "$Revision$"; } public AboutFrame(CortadoPipeline pipeline) { super("AboutFrame"); Configure configure = new Configure(); SourceInfo info = new SourceInfo(); setSize(200, 100); Button dbtn; d = new Dialog(this, "About Cortado", false); d.setVisible(true); TextArea ta = new TextArea("", 8, 40, TextArea.SCROLLBARS_NONE); d.add(ta); ta.appendText("This is Cortado " + configure.buildVersion + ".\n"); ta.appendText("Brought to you by Wim Taymans.\n"); ta.appendText("(C) Copyright 2004,2005,2006 Fluendo\n\n"); ta.appendText("Built on " + configure.buildDate + "\n"); ta.appendText("Built in " + configure.buildType + " mode.\n"); ta.appendText("Built from git branch " + info.branch + ", revision " + info.revision + "\n"); ta.appendText("Running on Java VM " + System.getProperty("java.version") + " from " + System.getProperty("java.vendor") + "\n"); if (pipeline.isAudioEnabled()) { if (pipeline.usingJavaX) { ta.appendText("Using the javax.sound backend."); } else { ta.appendText("Using the sun.audio backend.\n\n"); ta.appendText("NOTE: you should install the Java(TM) from Sun for better audio quality."); } } d.add(dbtn = new Button("OK"), BorderLayout.SOUTH); Dimension dim = d.getPreferredSize(); dim.height += 30; d.setSize(dim); dbtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { d.setVisible(false); } }); d.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { d.setVisible(false); } }); } } cortado-0.6.0/src/com/fluendo/player/CortadoPipeline.java100644 0 0 54576 11350725171 20563 0ustar 0 0 /* Cortado - a video player java applet * Copyright (C) 2005 Fluendo S.L. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. */ package com.fluendo.player; import java.util.*; import java.awt.*; import java.net.URL; import com.fluendo.jst.*; import com.fluendo.utils.*; public class CortadoPipeline extends Pipeline implements PadListener, CapsListener { private String url; private String userId; private String password; private boolean enableAudio; private boolean enableVideo; private boolean keepAspect; private boolean ignoreAspect; private int enableKate; private String enableKateLanguage = ""; private String enableKateCategory = ""; private Component component; private int bufferSize = -1; private int bufferLow = -1; private int bufferHigh = -1; private URL documentBase = null; private Cortado application; private Element httpsrc; private Element buffer; private Element demux; private Element videodec; private Element audiodec; private Element videosink; private Element audiosink; private Element v_queue, v_queue2, a_queue = null; private Element overlay; private Pad asinkpad, ovsinkpad, oksinkpad; private Pad apad, vpad; private Vector katedec = new Vector(); private Vector k_queue = new Vector(); private Element kselector = null; public boolean usingJavaX = false; private boolean setupVideoDec (String name) { videodec = ElementFactory.makeByName(name, "videodec"); if (videodec == null) { noSuchElement (name); return false; } add(videodec); return true; } public void padAdded(Pad pad) { Caps caps = pad.getCaps (); if (caps == null) { Debug.log(Debug.INFO, "pad added without caps: "+pad); return; } Debug.log(Debug.INFO, "pad added "+pad); String mime = caps.getMime(); if (enableAudio && mime.equals("audio/x-vorbis")) { if (a_queue != null) { Debug.log (Debug.INFO, "More than one audio stream detected, ignoring all except first one"); return; } a_queue = ElementFactory.makeByName("queue", "a_queue"); if (a_queue == null) { noSuchElement ("queue"); return; } // if we already have a video queue: We want smooth audio playback // over frame completeness, so make the video queue leaky if(v_queue != null) { v_queue.setProperty("leaky", "2"); // 2 == Queue.LEAK_DOWNSTREAM } audiodec = ElementFactory.makeByName("vorbisdec", "audiodec"); if (audiodec == null) { noSuchElement ("vorbisdec"); return; } a_queue.setProperty("maxBuffers","100"); add(a_queue); add(audiodec); pad.link(a_queue.getPad("sink")); a_queue.getPad("src").link(audiodec.getPad("sink")); if (!audiodec.getPad("src").link(asinkpad)) { postMessage (Message.newError (this, "audiosink already linked")); return; } apad = pad; audiodec.setState (PAUSE); a_queue.setState (PAUSE); } else if (enableVideo && mime.equals("video/x-theora")) { // Constructs a chain of the form // oggdemux -> v_queue -> theoradec -> v_queue2 -> videosink v_queue = ElementFactory.makeByName("queue", "v_queue"); v_queue2 = ElementFactory.makeByName("queue", "v_queue2"); if (v_queue == null) { noSuchElement ("queue"); return; } if (!setupVideoDec ("theoradec")) return; // if we have audio: We want smooth audio playback // over frame completeness if(a_queue != null) { v_queue.setProperty("leaky", "2"); // 2 == Queue.LEAK_DOWNSTREAM } v_queue.setProperty("maxBuffers","175"); v_queue2.setProperty("maxBuffers","1"); add(v_queue); add(v_queue2); pad.link(v_queue.getPad("sink")); v_queue.getPad("src").link(videodec.getPad("sink")); videodec.getPad("src").link(v_queue2.getPad("sink")); if (!v_queue2.getPad("src").link(ovsinkpad)) { postMessage (Message.newError (this, "videosink already linked")); return; } vpad = pad; videodec.setState (PAUSE); v_queue.setState (PAUSE); v_queue2.setState (PAUSE); } else if (enableVideo && mime.equals("image/jpeg")) { if (!setupVideoDec ("jpegdec")) { return; } videodec.setProperty ("component", component); pad.link(videodec.getPad("sink")); if (!videodec.getPad("src").link(ovsinkpad)) { postMessage (Message.newError (this, "videosink already linked")); return; } videodec.setState (PAUSE); } else if (enableVideo && mime.equals("video/x-smoke")) { if (!setupVideoDec ("smokedec")) { return; } videodec.setProperty ("component", component); pad.link(videodec.getPad("sink")); if (!videodec.getPad("src").link(ovsinkpad)) { postMessage (Message.newError (this, "videosink already linked")); return; } vpad = pad; videodec.setState (PAUSE); } else if (enableVideo && mime.equals("application/x-kate")) { Element tmp_k_queue, tmp_katedec, tmp_katesink; Pad tmp_kpad, tmp_ksinkpad; int kate_index = katedec.size(); Debug.debug("Found Kate stream, setting up pipeline branch"); /* dynamically create a queue/decoder/overlay pipeline */ tmp_k_queue = ElementFactory.makeByName("queue", "k_queue"+kate_index); if (tmp_k_queue == null) { noSuchElement ("queue"); return; } tmp_katedec = ElementFactory.makeByName("katedec", "katedec"+kate_index); if (tmp_katedec == null) { noSuchElement ("katedec"); return; } /* The selector is created when the first Kate stream is encountered */ if (kselector == null) { Debug.debug("No Kate selector yet, creating one"); /* insert an overlay before the video sink */ if (videodec != null) { ovsinkpad.unlink(); videodec.getPad("src").unlink(); overlay = ElementFactory.makeByName("kateoverlay", "overlay"); if (overlay == null) { noSuchElement ("overlay"); return; } ovsinkpad = overlay.getPad("videosink"); oksinkpad = overlay.getPad("katesink"); if (!videodec.getPad("src").link(ovsinkpad)) { postMessage (Message.newError (this, "Failed linking video decoder to overlay")); return; } add(overlay); overlay.setProperty ("component", component); overlay.getPad("videosrc").link(videosink.getPad("sink")); } else { Element fakesink = ElementFactory.makeByName("fakesink", "fakesink"); if (fakesink == null) { noSuchElement("fakesink"); return; } oksinkpad = fakesink.getPad("sink"); add(fakesink); } kselector = ElementFactory.makeByName("selector", "selector"); if (kselector == null) { noSuchElement ("selector"); return; } add(kselector); if (!kselector.getPad("src").link(oksinkpad)) { postMessage (Message.newError (this, "Failed linking Kate selector to overlay")); return; } kselector.setState (PAUSE); ((Cortado)component).status.setHaveSubtitles(true); } tmp_katesink = kselector; add(tmp_k_queue); add(tmp_katedec); tmp_kpad = pad; tmp_ksinkpad = tmp_katesink.getPad("sink"); /* link new elements together */ if (!pad.link(tmp_k_queue.getPad("sink"))) { postMessage (Message.newError (this, "Failed to link new Kate stream to queue")); return; } if (!tmp_k_queue.getPad("src").link(tmp_katedec.getPad("sink"))) { postMessage (Message.newError (this, "Failed to link new Kate queue to decoder")); return; } Pad new_selector_pad = kselector.requestSinkPad(tmp_katedec.getPad("src")); if (!tmp_katedec.getPad("src").link(new_selector_pad)) { postMessage (Message.newError (this, "kate sink already linked")); return; } tmp_katedec.setState (PAUSE); tmp_k_queue.setState (PAUSE); /* add to the lists */ katedec.addElement(tmp_katedec); k_queue.addElement(tmp_k_queue); /* if we have just added the one that was selected, link it now */ if (enableKate == katedec.size()-1) { doEnableKateIndex(enableKate); } else if (enableKate < 0 && (!enableKateLanguage.equals("") || !enableKateCategory.equals(""))) { String language = caps.getFieldString("language", ""); String category = caps.getFieldString("category", ""); boolean matching_language = enableKateLanguage.equals("") || enableKateLanguage.equals(language); boolean matching_category = enableKateCategory.equals("") || enableKateCategory.equals(category); if (matching_language && matching_category) { doEnableKateIndex(katedec.size()-1); } } } } public void padRemoved(Pad pad) { pad.unlink(); if (pad == vpad) { Debug.log(Debug.INFO, "video pad removed "+pad); ovsinkpad.unlink(); //oksinkpad.unlink(); // needed ???? vpad = null; } else if (pad == apad) { Debug.log(Debug.INFO, "audio pad removed "+pad); asinkpad.unlink(); apad = null; } } public void noMorePads() { boolean changed = false; Element el; Debug.log(Debug.INFO, "all streams detected"); if (apad == null && enableAudio) { Debug.log(Debug.INFO, "file has no audio, remove audiosink"); audiosink.setState(STOP); remove (audiosink); audiosink = null; changed = true; if (videosink != null) { videosink.setProperty ("max-lateness", Long.toString(Long.MAX_VALUE)); } } if (vpad == null && enableVideo) { Debug.log(Debug.INFO, "file has no video, remove videosink"); videosink.setState(STOP); if (overlay != null) { overlay.setState(STOP); } remove (videosink); remove (overlay); videosink = null; overlay = null; changed = true; } if (changed) scheduleReCalcState(); } public CortadoPipeline (Cortado cortado) { super("pipeline"); enableAudio = true; enableVideo = true; application = cortado; enableKate = -1; /* none by default */ } public void setUrl(String anUrl) { url = anUrl; } public String getUrl() { return url; } public void setUserId(String aUserId) { userId = aUserId; } public void setKeepAspect(boolean keep) { keepAspect = keep; } public void setIgnoreAspect(boolean ignore) { ignoreAspect = ignore; } public void setPassword(String aPassword) { password = aPassword; } public void enableAudio(boolean b) { enableAudio = b; } public boolean isAudioEnabled() { return enableAudio; } public void enableVideo(boolean b) { enableVideo = b; } public boolean isVideoEnabled() { return enableVideo; } /** * Finds a Kate stream from the given language and category names. * Returns a negative index if none is found. */ private int findKateStream(String language, String category) { int idx = -1; boolean has_language = !language.equals(""); boolean has_category = !category.equals(""); if (has_language || has_category) { for (int n=0; n= katedec.size()) return ""; return String.valueOf(((Element)katedec.elementAt(idx)).getProperty("category")); } protected String getKateStreamLanguage(int idx) { if (idx < 0 || idx >= katedec.size()) return ""; return String.valueOf(((Element)katedec.elementAt(idx)).getProperty("language")); } } cortado-0.6.0/src/com/fluendo/player/DurationScanner.java100644 0 0 21451 11350725171 20563 0ustar 0 0 /* Copyright (C) <2008> Maik Merten * Copyright (C) <2004> Wim Taymans (HTTPSrc.java parts) * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.player; import com.fluendo.utils.Base64Converter; import com.fluendo.utils.Debug; import com.jcraft.jogg.Packet; import com.jcraft.jogg.Page; import com.jcraft.jogg.StreamState; import com.jcraft.jogg.SyncState; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import java.text.MessageFormat; import java.util.Hashtable; import java.util.Locale; /** * * @author maik */ public class DurationScanner { final static int NOTDETECTED = -1; final static int UNKNOWN = 0; final static int VORBIS = 1; final static int THEORA = 2; private long contentLength = -1; private long responseOffset; private Hashtable streaminfo = new Hashtable(); private SyncState oy = new SyncState(); private Page og = new Page(); private Packet op = new Packet(); public DurationScanner() { oy.init(); } private InputStream openWithConnection(URL url, String userId, String password, long offset) throws IOException { // lifted from HTTPSrc.java InputStream dis = null; String userAgent = "Cortado"; URLConnection uc = url.openConnection(); uc.setRequestProperty("Connection", "Keep-Alive"); String range; if (offset != 0 && contentLength != -1) { range = "bytes=" + offset + "-" + (contentLength - 1); } else if (offset != 0) { range = "bytes=" + offset + "-"; } else { range = null; } if (range != null) { Debug.info("doing range: " + range); uc.setRequestProperty("Range", range); } uc.setRequestProperty("User-Agent", userAgent); if (userId != null && password != null) { String userPassword = userId + ":" + password; String encoding = Base64Converter.encode(userPassword.getBytes()); uc.setRequestProperty("Authorization", "Basic " + encoding); } uc.setRequestProperty("Content-Type", "application/octet-stream"); /* This will send the request. */ dis = uc.getInputStream(); String responseRange = uc.getHeaderField("Content-Range"); if (responseRange == null) { Debug.info("Response contained no Content-Range field, assuming offset=0"); responseOffset = 0; } else { try { MessageFormat format = new MessageFormat("bytes {0,number}-{1,number}"); format.setLocale(Locale.US); java.lang.Object parts[] = format.parse(responseRange); responseOffset = ((Number) parts[0]).longValue(); if (responseOffset < 0) { responseOffset = 0; } Debug.debug("Stream successfully with offset " + responseOffset); } catch (Exception e) { Debug.info("Error parsing Content-Range header"); responseOffset = 0; } } contentLength = uc.getHeaderFieldInt("Content-Length", -1) + responseOffset; return dis; } private void determineType(Packet packet, StreamInfo info) { int ret; Class c; // try theora try { c = Class.forName("com.fluendo.plugin.TheoraDec"); com.fluendo.plugin.OggPayload pl = (com.fluendo.plugin.OggPayload)c.newInstance(); ret = pl.takeHeader(packet); if (ret >= 0) { info.decoder = pl; info.type = THEORA; return; } } catch (Throwable e) { } // try vorbis try { c = Class.forName("com.fluendo.plugin.VorbisDec"); com.fluendo.plugin.OggPayload pl = (com.fluendo.plugin.OggPayload)c.newInstance(); ret = pl.takeHeader(packet); if (ret >= 0) { info.decoder = pl; info.type = VORBIS; return; } } catch (Throwable e) { } info.type = UNKNOWN; } public float getDurationForBuffer(byte[] buffer, int bufbytes) { long time = -1; int offset = oy.buffer(bufbytes); java.lang.System.arraycopy(buffer, 0, oy.data, offset, bufbytes); oy.wrote(bufbytes); while (oy.pageout(og) == 1) { Integer serialno = new Integer(og.serialno()); StreamInfo info = (StreamInfo) streaminfo.get(serialno); if (info == null) { info = new StreamInfo(); info.streamstate = new StreamState(); info.streamstate.init(og.serialno()); streaminfo.put(serialno, info); Debug.info("DurationScanner: created StreamState for stream no. " + serialno); } info.streamstate.pagein(og); while (info.streamstate.packetout(op) == 1) { int type = info.type; if (type == NOTDETECTED) { determineType(op, info); info.startgranule = og.granulepos(); } switch (type) { case VORBIS: { com.fluendo.plugin.OggPayload pl = info.decoder; long t = pl.granuleToTime(og.granulepos()) - pl.granuleToTime(info.startgranule); if (t > time) { time = t; } } break; case THEORA: { com.fluendo.plugin.OggPayload pl = info.decoder; long t = pl.granuleToTime(og.granulepos()) - pl.granuleToTime(info.startgranule); if (t > time) { time = t; } } break; } } } return time / (float)com.fluendo.jst.Clock.SECOND; } public float getDurationForURL(URL url, String user, String password) { try { int headbytes = 24 * 1024; int tailbytes = 128 * 1024; float time = 0; byte[] buffer = new byte[1024]; InputStream is = openWithConnection(url, user, password, 0); int read = 0; long totalbytes = 0; read = is.read(buffer); // read beginning of the stream while (totalbytes < headbytes && read > 0) { totalbytes += read; float t = getDurationForBuffer(buffer, read); time = t > time ? t : time; read = is.read(buffer); } is.close(); is = openWithConnection(url, user, password, contentLength - tailbytes); if(responseOffset == 0) { Debug.warning("DurationScanner: Couldn't complete duration scan due to failing range requests!"); return -1; } read = is.read(buffer); // read tail until eos, also abort if way too many bytes have been read while (read > 0 && totalbytes < (headbytes + tailbytes) * 2) { totalbytes += read; float t = getDurationForBuffer(buffer, read); time = t > time ? t : time; read = is.read(buffer); } return time; } catch (IOException e) { Debug.error(e.toString()); return -1; } } private class StreamInfo { public com.fluendo.plugin.OggPayload decoder; public int type = NOTDETECTED; public long startgranule; public StreamState streamstate; public boolean ready = false; } public static void main(String[] args) throws IOException { URL url; url = new URL(args[0]); System.out.println(new DurationScanner().getDurationForURL(url, null, null)); } } cortado-0.6.0/src/com/fluendo/player/Status.java100644 0 0 47065 11350725171 16760 0ustar 0 0 /* Cortado - a video player java applet * Copyright (C) 2004 Fluendo S.L. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. */ package com.fluendo.player; import java.awt.*; import java.awt.image.*; import java.awt.event.*; import java.awt.font.*; import java.util.*; public class Status extends Component implements MouseListener, MouseMotionListener { private static final long serialVersionUID = 1L; private int bufferPercent; private boolean buffering; private String message; private String error; private Rectangle r; private Component component; private Font font = new Font("SansSerif", Font.PLAIN, 10); private Font boldFont = null; private boolean haveAudio; private boolean haveSubtitles; private boolean havePercent; private boolean seekable; private boolean live; private boolean showSpeaker; private boolean showSubtitles; private boolean clearedScreen; private static final int NONE = -1; private static final int BUTTON1 = 0; private static final int BUTTON2 = 1; private static final int SEEKER = 2; private static final int SEEKBAR = 3; private static final int AUDIO = 4; private static final int SUBTITLES = 5; private int clicked = NONE; private Color colors[] = { Color.black, Color.black, Color.black, Color.black, Color.black, Color.black }; private static final int SPEAKER_WIDTH = 12; private static final int SPEAKER_HEIGHT = 10; private static final int TIME_WIDTH = 38; private static final int SEEK_TIME_GAP = 10; private static final int THUMB_WIDTH = 9; public static final int STATE_STOPPED = 0; public static final int STATE_PAUSED = 1; public static final int STATE_PLAYING = 2; private int state = STATE_STOPPED; private double position = 0; private long time; private double duration; private long byteDuration; private long bytePosition; private String speaker = "\0\0\0\0\0\357\0\0\357U\27" + "\36\0\0\0\0\357\357\0\0" + "\0\357U\30\0\0\0\357\0\357" + "\0\357\0\0\357\23\357" + "\357\357\0\34\357\0Z\357\0" + "\357\\\357\0)+F\357\0\0\357" + "\0\357r\357Ibz\221\357" + "\0\0\357\0\357r\357\357\357" + "\276\323\357\0Z\357\0\357" + "\\\0\0\0\357\357\357\0" + "\357\0\0\357\0\0\0\0\0\357" + "\357\0\0\0\357\\\0\0\0" + "\0\0\0\357\0\0\357\\\0\0"; private Image speakerImg; private int speakerWidth; // width of the speaker icon or zero if hidden private int subtitlesWidth; // width of the subtitles icon or zero if hidden private Vector listeners = new Vector(); public Image createImage(Component comp, String s, int w, int h) { int[] pixels = new int[w * h]; for (int i = 0; i < w * h; i++) { pixels[i] = 0xff000000 | (s.charAt(i) << 16) | (s.charAt(i) << 8) | (s.charAt(i)); } return comp.getToolkit().createImage( new MemoryImageSource(w, h, pixels, 0, w)); } public Status(Component comp) { component = comp; speakerImg = createImage(comp, speaker, SPEAKER_WIDTH, SPEAKER_HEIGHT); } public void addStatusListener(StatusListener l) { listeners.addElement(l); } public void removeStatusListener(StatusListener l) { listeners.removeElement(l); } public void notifyNewState(int newState) { for (Enumeration e = listeners.elements(); e.hasMoreElements();) { ((StatusListener) e.nextElement()).onState(newState); } } public void notifySeek(double position) { for (Enumeration e = listeners.elements(); e.hasMoreElements();) { ((StatusListener) e.nextElement()).onSeek(position); } } public void notifyAudio() { for (Enumeration e = listeners.elements(); e.hasMoreElements();) { ((StatusListener) e.nextElement()).onAudio(); } } public void notifySubtitles(int x, int y) { for (Enumeration e = listeners.elements(); e.hasMoreElements();) { ((StatusListener) e.nextElement()).onSubtitles(x, y); } } public void update(Graphics g) { paint(g); } private void paintBox(Graphics g) { g.setColor(Color.darkGray); g.drawRect(0, 0, r.width - 1, r.height - 1); g.setColor(Color.black); g.fillRect(1, 1, r.width - 2, r.height - 2); } private void paintPercent(Graphics g) { if (havePercent) { g.setColor(Color.white); g.drawString("" + bufferPercent + "%", r.width - 26 - speakerWidth -subtitlesWidth, r.height - 2); } } private void paintButton1(Graphics g) { int x,y,w,h; x = 1; y = 1; w = r.height-2; h = r.height-2; g.setColor(Color.darkGray); g.drawRect(x, y, w, h); g.setColor(colors[BUTTON1]); g.fillRect(x+1, y+1, w-1, h-1); if (state == STATE_PLAYING) { g.setColor(Color.white); if (live) { /* STOP */ g.fillRect((int)(w * .4), (int)(w * .4), (int)(w * .5), (int)(w * .5)); } else { /* PAUSE */ g.fillRect((int)(w * .4), (int)(h * .4), (int)(w * .2), (int)(h * .5)); g.fillRect((int)(w * .7), (int)(h * .4), (int)(w * .2), (int)(h * .5)); } } else { int triangleX[] = { (int)(w*.4), (int)(w*.4), (int)(w*.9) }; int triangleY[] = { (int)(w*.3), (int)(w*.9), (int)(w*.6) }; g.setColor(Color.white); g.fillPolygon(triangleX, triangleY, 3); } } private void paintButton2(Graphics g) { int x,y,w,h; x = r.height + 1; y = 1; w = r.height - 2; h = r.height - 2; g.setColor(Color.darkGray); g.drawRect(x, y, w, h); g.setColor(colors[BUTTON2]); g.fillRect(x+1, y+1, w-1, h-1); g.setColor(Color.white); g.fillRect(r.height + (int)(w * .4), (int)(w * .4), (int)(w * .5), (int)(w * .5)); } private void paintMessage(Graphics g, int pos) { if (message != null) { g.setColor(Color.white); g.drawString(message, pos, r.height - 2); } } private void paintBuffering(Graphics g, int pos) { g.setColor(Color.white); g.drawString("Buffering", pos, r.height - 2); } /* * Get the inclusive bounding rectangle of the seek bar */ private Rectangle getSeekBarRect() { return new Rectangle(r.height*2 + 1, 2, r.width - SEEK_TIME_GAP - TIME_WIDTH - speakerWidth - subtitlesWidth - (r.height * 2), r.height - 4); } /* * Get the inclusive bounding rectangle of the seek bar thumb */ private Rectangle getThumbRect() { Rectangle seekRect = getSeekBarRect(); int availableWidth = seekRect.width - THUMB_WIDTH; int pos = (int)(availableWidth * position); return new Rectangle(pos + seekRect.x, 1, THUMB_WIDTH, r.height - 2); } private void paintSeekBar(Graphics g) { Rectangle sr = getSeekBarRect(); Rectangle tr = getThumbRect(); // Bounding rectangle g.setColor(Color.darkGray); g.drawRect(sr.x, sr.y, sr.width, sr.height); // Progress bar g.setColor(Color.gray); g.fillRect(sr.x + 2, sr.y + 3, tr.x - (sr.x + 2), sr.height - 6); // Thumb g.setColor(Color.white); g.drawLine(tr.x + 1, tr.y, tr.x + tr.width - 1, tr.y); // Top g.drawLine(tr.x + 1, tr.y + tr.height, tr.x + tr.width - 1, tr.y + tr.height); // Bottom g.drawLine(tr.x, tr.y + 1, tr.x, tr.y + tr.height - 1); // Left g.drawLine(tr.x + tr.width, tr.y + 1, tr.x + tr.width, tr.y + tr.height - 1); // Right // Thumb interior g.setColor(colors[SEEKER]); g.fillRect(tr.x + 1, tr.y + 1, tr.width - 1, tr.height - 1); } private void paintTime(Graphics g) { long hour, min, sec; int end; if (time < 0) return; sec = time % 60; min = time / 60; hour = min / 60; min %= 60; r = getBounds(); end = r.width - speakerWidth - subtitlesWidth - TIME_WIDTH; g.setColor(Color.white); g.drawString("" + hour + ":" + (min < 10 ? "0" + min : "" + min) + ":" + (sec < 10 ? "0" + sec : "" + sec), end, r.height - 2); } private void paintSpeaker(Graphics g) { if (haveAudio) { g.drawImage(speakerImg, r.width - SPEAKER_WIDTH - subtitlesWidth, r.height - SPEAKER_HEIGHT - 1, null); } } private Rectangle getSubtitlesBounds() { int x = r.width - subtitlesWidth + 1; int y = 1; int w = r.height * 3 / 2 - 2; int h = r.height - 2; return new Rectangle(x, y, w, h); } private void paintSubtitles(Graphics g) { if (haveSubtitles) { Rectangle sb = getSubtitlesBounds(); int font_height = r.height - 2; g.setColor(Color.darkGray); g.drawRect(sb.x, sb.y, sb.width, sb.height); g.setColor(colors[SUBTITLES]); g.fillRect(sb.x+1, sb.y+1, sb.width-1, sb.height-1); if (boldFont == null) boldFont = new Font("SansSerif", Font.BOLD, font_height); g.setColor(Color.white); Font previousFont = g.getFont(); g.setFont(boldFont); FontMetrics fm = g.getFontMetrics(); float cc_w = fm.stringWidth("CC"); float cc_h = fm.getAscent()-fm.getDescent(); float button_midx = sb.x + sb.width/2.0f; float button_midy = sb.y + sb.height/2.0f; g.drawString("CC", (int)(button_midx - cc_w/2.0f + 0.5f), (int)(button_midy + cc_h/2.0f + 0.5f)); g.setFont(previousFont); } } public void paint(Graphics g) { if (!isVisible() && clearedScreen) return; r = getBounds(); if(!isVisible() && !clearedScreen) { g.clearRect(r.x, r.y, r.width, r.height); clearedScreen = true; return; } clearedScreen = false; int pos = 0; Image img = component.createImage(r.width, r.height); if (img == null) return; Graphics g2 = img.getGraphics(); if (g2 == null) return; g2.setFont(font); paintBox(g2); if (!buffering) { paintButton1(g2); } if (!live) { paintButton2(g2); pos = r.height*2; } else { pos = r.height; } if (buffering) { paintPercent(g2); paintBuffering(g2, pos + 3); } else if (state == STATE_STOPPED || !seekable) { paintMessage(g2, pos + 3); paintTime(g2); } else if (seekable) { paintSeekBar(g2); paintTime(g2); } if (showSpeaker) { paintSpeaker(g2); } if (showSubtitles) { paintSubtitles(g2); } g.drawImage(img, r.x, r.y, null); img.flush(); } public void setBufferPercent(boolean buffering, int bp) { boolean changed; changed = this.buffering != buffering; changed |= this.bufferPercent != bp; if (changed) { this.buffering = buffering; this.bufferPercent = bp; component.repaint(); } } public void setTime(double seconds) { if (clicked == NONE) { double newPosition; if (seconds < duration || seekable) time = (long) seconds; else time = (long) duration; if(duration > -1) { newPosition = ((double) time) / duration; if (newPosition != position) { position = newPosition; component.repaint(); } } else { newPosition = ((double)bytePosition) / (double)byteDuration; position = newPosition; component.repaint(); } } } public void setDuration(double seconds) { duration = seconds; component.repaint(); } public void setByteDuration(long bytes) { this.byteDuration = bytes; if(duration == -1) { position = ((double)bytePosition) / (double)byteDuration; component.repaint(); } } public void setBytePosition(long bytes) { this.bytePosition = bytes; if(duration == -1) { position = ((double)bytePosition) / (double)byteDuration; component.repaint(); } } public void setMessage(String m) { message = m; component.repaint(); } public void setHaveAudio(boolean a) { haveAudio = a; component.repaint(); } public void setHaveSubtitles(boolean a) { haveSubtitles = a; subtitlesWidth = showSubtitles && haveSubtitles ? r.height * 3 / 2 : 0; component.repaint(); } public void setHavePercent(boolean p) { havePercent = p; component.repaint(); } public void setSeekable(boolean s) { seekable = s; component.repaint(); } public void setLive(boolean l) { live = l; component.repaint(); } public void setShowSpeaker(boolean s) { showSpeaker = s; speakerWidth = s ? SPEAKER_WIDTH : 0; component.repaint(); } public void setShowSubtitles(boolean s) { showSubtitles = s; subtitlesWidth = showSubtitles && haveSubtitles ? r.height * 3 / 2 : 0; component.repaint(); } public void setState(int aState) { if (state != aState) { state = aState; component.repaint(); } } private boolean intersectButton1(MouseEvent e) { if (r == null) return false; return (e.getX() >= 0 && e.getX() <= r.height-2 && e.getY() > 0 && e.getY() <= r.height-2); } private boolean intersectButton2(MouseEvent e) { if (r == null) return false; return (e.getX() >= r.height && e.getX() <= r.height + r.height-2 && e.getY() > 0 && e.getY() <= r.height-2); } private boolean intersectAudio(MouseEvent e) { // TODO return false; } private boolean intersectSubtitles(MouseEvent e) { if (r == null) return false; Rectangle bounds = getSubtitlesBounds(); return (e.getX() >= bounds.x && e.getX() <= bounds.x+bounds.width-2 && e.getY() > 0 && e.getY() <= bounds.height-2); } private boolean intersectSeeker(MouseEvent e) { r = getBounds(); Rectangle tr = getThumbRect(); return tr.contains(e.getPoint()); } private boolean intersectSeekbar(MouseEvent e) { r = getBounds(); Rectangle sr = getSeekBarRect(); return sr.contains(e.getPoint()); } private int findComponent(MouseEvent e) { if (!buffering && intersectButton1(e)) return BUTTON1; else if (intersectButton2(e)) return BUTTON2; else if (showSpeaker && haveAudio && intersectAudio(e)) return AUDIO; else if (showSubtitles && haveSubtitles && intersectSubtitles(e)) return SUBTITLES; else if (seekable && intersectSeeker(e)) return SEEKER; else if (seekable && intersectSeekbar(e)) return SEEKBAR; else return NONE; } public void cancelMouseOperation() { for (int n=0; n 1.0) newPosition = 1.0; if (newPosition != position) { position = newPosition; time = (long) (duration * position); component.repaint(); } } } } private boolean testIntersection(boolean in, int idx) { if (in) { if (colors[idx] != Color.gray) { colors[idx] = Color.gray; return true; } } else { if (colors[idx] != Color.black) { colors[idx] = Color.black; return true; } } return false; } public void mouseMoved(MouseEvent e) { boolean needRepaint = false; e.translatePoint(-1, -1); if (!buffering) { if (testIntersection(intersectButton1(e), BUTTON1)) needRepaint = true; } if (testIntersection(intersectButton2(e), BUTTON2)) needRepaint = true; if (seekable) { if (testIntersection(intersectSeeker(e), SEEKER)) needRepaint = true; } if (haveAudio && showSpeaker) { if (testIntersection(intersectAudio(e), AUDIO)) needRepaint = true; } if (haveSubtitles && showSubtitles) { if (testIntersection(intersectSubtitles(e), SUBTITLES)) needRepaint = true; } if (needRepaint) component.repaint(); } } cortado-0.6.0/src/com/fluendo/player/StatusListener.java100644 0 0 1766 11350725171 20444 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.player; public interface StatusListener { public void onState (int newState); public void onSeek (double position); public void onAudio (); public void onSubtitles (int x, int y); } cortado-0.6.0/src/com/fluendo/plugin/AudioSink.java100644 0 0 31443 11274362076 17364 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.plugin; import com.fluendo.jst.*; import com.fluendo.utils.*; public abstract class AudioSink extends Sink implements ClockProvider { protected RingBuffer ringBuffer = null; private class AudioClock extends SystemClock { private long lastTime = -1; private long diff = -1; private boolean started = false; public void setStarted(boolean s) { started = s; if (started) { diff = -1; lastTime = -1; } } protected long getInternalTime() { long samples; long result; long timePos; long now; synchronized (ringBuffer) { if (ringBuffer == null || ringBuffer.rate == 0) return 0; samples = ringBuffer.samplesPlayed(); timePos = samples * Clock.SECOND / ringBuffer.rate; if (started) { /* interpolate as the position can jump a lot */ now = System.currentTimeMillis() * Clock.MSECOND; if (diff == -1) { diff = now; } if (timePos != lastTime) { lastTime = timePos; diff = now - timePos; } result = now - diff; //System.out.println("time: "+result+", now: "+now+", diff: "+diff+", timePos: "+timePos); } else { result = timePos; //System.out.println("time: "+result); } } //System.out.println("time: "+result+" samples: "+samples+" sampletime: "+timePos); return result; } }; private AudioClock audioClock = new AudioClock(); public Clock provideClock() { return audioClock; } protected class RingBuffer implements Runnable { protected byte[] buffer; private int state; private Thread thread; private long nextSample; private boolean flushing; private boolean autoStart; private boolean opened; private static final int STOP = 0; private static final int PAUSE = 1; private static final int PLAY = 2; public int bps, sps; public byte[] emptySeg; public long playSeg; public int segTotal; public int segSize; public int rate, channels; public void run() { boolean running = true; while (running) { synchronized (this) { if (state != PLAY) { while (state == PAUSE) { try { notifyAll(); wait(); } catch (InterruptedException ie) {} } if (state == STOP) { running = false; break; } } } int segNum = (int) (playSeg % segTotal); int index = segNum * segSize; int ret, toWrite; toWrite = segSize; while (toWrite > 0) { ret = write (buffer, index, segSize); if (ret == -1) break; toWrite -= ret; } clear (segNum); synchronized (this) { //System.out.println("writen seg "+playSeg); playSeg++; notifyAll(); } } } public synchronized void setFlushing(boolean flushing) { this.flushing = flushing; clearAll(); if (flushing) { pause(); } } protected void startWriteThread () { thread = new Thread(this, "cortado-audiosink-ringbuffer"); thread.start(); try { wait(); } catch (InterruptedException ie) {} } public synchronized boolean acquire(Caps caps) { boolean res; if (thread != null) return false; if (opened) return false; String mime = caps.getMime(); if (!mime.equals ("audio/raw")) return false; rate = caps.getFieldInt("rate", 44100); channels = caps.getFieldInt("channels", 1); bps = 2 * channels; if ((res = open (this)) == false) return res; opened = true; Debug.log(Debug.INFO, "audio: segSize: "+ segSize); Debug.log(Debug.INFO, "audio: segTotal: "+ segTotal); segTotal++; buffer = new byte[segSize * segTotal]; sps = segSize / bps; state = PAUSE; nextSample = 0; playSeg = 0; startWriteThread(); return res; } public synchronized boolean isAcquired() { return opened; } public boolean release() { stop(); synchronized (this) { if (opened) { if (close(this) == false) return false; } opened = false; } return true; } private synchronized boolean waitSegment() { if (flushing) return false; if (state != PLAY && autoStart) { play(); } try { if (state != PLAY) { //System.out.println("waitSegment: not playing"); return false; } wait(); if (flushing) return false; if (state != PLAY) return false; } catch (InterruptedException ie) {} return true; } public int commit (byte[] data, long sample, int offset, int len) { int idx; if (sample == -1) { sample = nextSample; } if (sample < 0) { return len; } if (nextSample != -1) { if (Math.abs(sample - nextSample) < (rate / 10)) sample = nextSample; else System.out.println("discont: found "+sample+" expected "+nextSample); } idx = 0; nextSample = sample + (len / bps); while (len > 0) { long writeSeg; int writeOff; int writeLen = 0; long diff = -1; writeSeg = sample / sps; writeOff = (int) ((sample % sps) * bps); while (true) { /* get the currently playing segment */ synchronized (this) { /* see how far away it is from the write segment */ diff = writeSeg - playSeg; } /* play segment too far ahead, we need to drop */ if (diff < 0) { /* we need to drop one segment at a time, pretend we wrote a * segment. */ writeLen = Math.min (segSize, len); //System.out.println("dropped "+diff); break; } else { /* write segment is within writable range, we can break the loop and * start writing the data. */ if (diff < segTotal) break; /* else we need to wait for the segment to become writable. */ //System.out.println("wait "+diff); if (!waitSegment ()) { //System.out.println("flushing"); return -1; } } } if (diff >= 0) { int writeSegRel; /* we can write now */ writeSegRel = (int) (writeSeg % segTotal); writeLen = Math.min (segSize - writeOff, len); System.arraycopy (data, idx, buffer, writeSegRel * segSize + writeOff, writeLen); } len -= writeLen; idx += writeLen; sample += writeLen / bps; } return len; } public long samplesPlayed () { long delay, samples; long seg; /* get the number of samples not yet played */ delay = delay (); seg = Math.max (0, playSeg - 1); samples = (seg * sps); //System.out.println("samples: "+samples+" delay: "+delay); if (samples >= delay) samples -= delay; else samples = 0; return samples; } public synchronized void clear (long segNum) { int index = ((int)(segNum % segTotal)) * segSize; System.arraycopy (emptySeg, 0, buffer, index, segSize); } public synchronized void clearAll () { for (int i = 0; i < segTotal; i++) { clear (i); } } public synchronized void setSample (long sample) { //System.out.println("setSample: "+sample); if (sample == -1) sample = 0; playSeg = sample / sps; nextSample = sample; clearAll(); } public synchronized void setAutoStart (boolean start) { autoStart = start; } public boolean play () { synchronized (this) { if (flushing) return false; state = PLAY; audioClock.setStarted(true); notifyAll(); } Debug.log(Debug.DEBUG, this+" playing"); return true; } public boolean pause () { synchronized (this) { Debug.log(Debug.DEBUG, this+" pausing"); state = PAUSE; audioClock.setStarted(false); notifyAll(); if (thread != null) { try { Debug.log(Debug.DEBUG, this+" waiting for pause"); wait(); } catch (InterruptedException ie) {} } } Debug.log(Debug.DEBUG, this+" paused"); return true; } public boolean stop () { synchronized (this) { Debug.log(Debug.DEBUG, this+" stopping"); state = STOP; audioClock.setStarted(false); notifyAll(); } if (thread != null) { try { Debug.log(Debug.DEBUG, this+" joining thread"); thread.join(); thread = null; } catch (InterruptedException ie) {} } Debug.log(Debug.DEBUG, this+" stopped"); return true; } public synchronized int getState() { return state; } } // Test whether the audio sink is likely to work. // Called before the ring buffer is acquired public boolean test() { return true; } protected WaitStatus doSync (long time) { return WaitStatus.newOK(); } protected boolean doEvent (Event event) { switch (event.getType()) { case Event.FLUSH_START: ringBuffer.setFlushing (true); break; case Event.FLUSH_STOP: ringBuffer.setFlushing (false); break; case Event.NEWSEGMENT: break; case Event.EOS: // wait for completion, perform blocking drain of buffers drain(); break; } return true; } protected int render (Buffer buf) { long sample; long time; if (buf.isFlagSet (com.fluendo.jst.Buffer.FLAG_DISCONT)) ringBuffer.nextSample = -1; time = buf.timestamp - segStart; if (time < 0) return Pad.OK; time += baseTime; sample = time * ringBuffer.rate / Clock.SECOND; //System.out.println("render sample: "+sample+" time: "+buf.timestamp); ringBuffer.commit (buf.data, sample, buf.offset, buf.length); return Pad.OK; } protected boolean setCapsFunc (Caps caps) { boolean res; ringBuffer.release(); res = ringBuffer.acquire(caps); return res; } protected int changeState (int transition) { int result; switch (transition) { case STOP_PAUSE: ringBuffer = createRingBuffer(); ringBuffer.setFlushing(false); break; case PAUSE_PLAY: //long sample = baseTime * ringBuffer.rate / Clock.SECOND; //ringBuffer.setSample (sample); ringBuffer.setAutoStart (true); break; case PLAY_PAUSE: reset(); ringBuffer.setAutoStart (false); ringBuffer.pause(); break; case PAUSE_STOP: ringBuffer.setFlushing(true); break; } result = super.changeState(transition); switch (transition) { case PAUSE_STOP: ringBuffer.release(); break; } return result; } /* * Block until audio playback is finished */ protected void drain() { if (ringBuffer.rate <= 0) { return; } /* need to start playback before we can drain, but only when * we have successfully negotiated a format and thus acquired the * ringbuffer. */ if (!ringBuffer.isAcquired()) { // FIXME make it work like it does in GstBaseAudioSink // ringBuffer.acquire(...); return; } if (ringBuffer.getState() != PLAY) { ringBuffer.play(); } if (ringBuffer.nextSample != -1) { long time = ringBuffer.nextSample * Clock.SECOND / ringBuffer.rate; Clock.ClockID id = audioClock.newSingleShotID(time); Debug.log(Debug.DEBUG, this+" waiting until t=" + ((double)time / Clock.SECOND) + "s for playback to finish"); id.waitID(); ringBuffer.nextSample = -1; } } protected abstract RingBuffer createRingBuffer(); protected abstract boolean open (RingBuffer ring); protected abstract boolean close (RingBuffer ring); protected abstract int write (byte[] data, int offset, int length); protected abstract long delay (); protected abstract void reset (); } cortado-0.6.0/src/com/fluendo/plugin/AudioSinkJ2.java100644 0 0 15503 11337541306 17552 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.plugin; import com.fluendo.jst.*; import com.fluendo.utils.*; import javax.sound.sampled.*; public class AudioSinkJ2 extends AudioSink { public static final int SEGSIZE = 2048; private SourceDataLine line = null; private int channels; private long samplesWritten; protected RingBuffer createRingBuffer() { return new RingBuffer(); } protected boolean open (RingBuffer ring) { channels = ring.channels; line = openLine(ring.channels, ring.rate); if (line == null) { postMessage (Message.newError (this, "Could not open audio device.")); return false; } Debug.log(Debug.INFO, "line info: available: "+ line.available()); Debug.log(Debug.INFO, "line info: buffer: "+ line.getBufferSize()); Debug.log(Debug.INFO, "line info: framePosition: "+ line.getFramePosition()); ring.segSize = SEGSIZE*channels*2; ring.segTotal = line.getBufferSize() / ring.segSize; while (ring.segTotal < 4) { ring.segSize >>= 1; ring.segTotal = line.getBufferSize() / ring.segSize; } ring.emptySeg = new byte[ring.segSize]; samplesWritten = 0; line.start(); return true; } protected SourceDataLine openLine(int channels, int rate) { AudioFormat format = new AudioFormat(rate, 16, channels, true, true); DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); SourceDataLine line = null; try { Mixer.Info[] mixers = AudioSystem.getMixerInfo(); /* On linux, the default implementation gives terribly inaccurate results * from line.available(), so we can't keep sync. Modern JVMs have an ALSA * implementation that doesn't suck, so use that if available. */ for(int i=0; i < mixers.length; i++) { Debug.log(Debug.INFO, "mixer description: " + mixers[i].getDescription() + ", vendor: " + mixers[i].getVendor()); /* Apparently either description or vendor might contain 'ALSA' - on * my system, it's vendor */ String desc = mixers[i].getDescription(); String vendor = mixers[i].getVendor(); if(desc.indexOf("ALSA") >= 0 || vendor.indexOf("ALSA") >= 0) { /* Unfortunately, the alsa devices include useless ones that we have * no sane way of filtering out! Hence this insanity. */ if (desc.indexOf("IEC958") >= 0) continue; try { Line.Info[] lines = AudioSystem.getMixer(mixers[i]). getSourceLineInfo(info); for (int j=0; j < lines.length; j++) { Debug.log(Debug.INFO, "Mixer supports line: " + lines[j].toString()); AudioFormat[] formats = ((DataLine.Info)lines[j]).getFormats(); for(int k=0; k < formats.length; k++) Debug.log(Debug.INFO, "Format: " + formats[k].toString()); } Debug.log(Debug.INFO, "Attempting to get a line from ALSA mixer"); line = (SourceDataLine) AudioSystem.getMixer( mixers[i]).getLine(info); /* Got one. Excellent. Try it. */ line.open(format); break; } catch (Exception e) { if (line != null) { line.close(); line = null; } /* Don't care too much; we'll fall through to the default case * later, and do proper error handling there */ Debug.log(Debug.INFO, "mixer: " + mixers[i].getDescription() + " failed: " + e); } } } /* If that failed, use the default line. */ if (line == null) { line = (SourceDataLine) AudioSystem.getLine(info); line.open(format); } } catch (javax.sound.sampled.LineUnavailableException e) { Debug.error(e.toString()); return null; } catch (Exception e) { Debug.error(e.toString()); return null; } return line; } public boolean test() { SourceDataLine line; line = openLine(2, 44000); if (line == null) { return false; } line.close(); return true; } protected boolean close (RingBuffer ring) { line.stop(); line.close(); return true; } protected int write (byte[] data, int offset, int length) { int written = 0; if ( offset < 0 || offset >= data.length || offset + length > data.length || length <= 0 ) { // This happens on stop for some reason Debug.debug( "Invalid audio write offset=" + offset + ", length=" + length + ", data.length=" + data.length ); return length; } // Need to avoid blocking due to lock contention in line.getFramePosition() in Java 6. while ( true ) { int available = line.available(); if ( length > available ) { if ( available > 0 ) { Debug.debug( "Doing partial audio write of " + available + " bytes" ); written += line.write( data, offset, available ); offset += available; length -= available; } if ( length > 0 ) { try { // Sleep for a quarter of the buffer time before we fill it up again AudioFormat format = line.getFormat(); long sleepTime = (long)(line.getBufferSize() * 1000 / format.getSampleRate() / format.getSampleSizeInBits() * 8 / (2*channels));//ee Debug.debug( "Sleeping for " + sleepTime + "ms" ); Thread.sleep(sleepTime); } catch ( InterruptedException e ) {} continue; } } else { Debug.debug( "Doing complete audio write of " + length + " bytes" ); written += line.write( data, offset, length ); } break; } samplesWritten += written / (2 * channels); return written; } protected long delay () { int frame; long delay; frame = line.getFramePosition(); delay = samplesWritten - frame; return delay; } protected void reset () { Debug.log(Debug.DEBUG, "reset audio: "+ line); line.flush(); samplesWritten = line.getFramePosition(); Debug.log(Debug.DEBUG, "samples written: "+ samplesWritten); } public String getFactoryName () { return "audiosinkj2"; } } cortado-0.6.0/src/com/fluendo/plugin/AudioSinkSA.java100644 0 0 15531 11270111317 17572 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.plugin; import java.io.*; import sun.audio.*; import com.fluendo.utils.*; public class AudioSinkSA extends AudioSink { private static final int BUFFER = 16 * 1024; private static final int SEGSIZE = 256; private static final int DELAY = 8 * 1000; /* in samples at 8000 Hz */ private double rateDiff; private int delay; private static final boolean ZEROTRAP=true; private static final short BIAS=0x84; private static final int CLIP=32635; private static final byte[] exp_lut = { 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 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, 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, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 }; /* muLaw header */ private static final short[] header = { 0x2e, 0x73, 0x6e, 0x64, // header in be 0x00, 0x00, 0x00, 0x18, // offset 0x7f, 0xff, 0xff, 0xff, // length 0x00, 0x00, 0x00, 0x01, // ulaw 0x00, 0x00, 0x1f, 0x40, // frequency 0x00, 0x00, 0x00, 0x01 // channels }; private int headerPos; private final int toUlaw(int sample) { int sign, exponent, mantissa, ulawbyte; if (sample>32767) sample=32767; else if (sample<-32768) sample=-32768; /* Get the sample into sign-magnitude. */ sign = (sample >> 8) & 0x80; /* set aside the sign */ if (sign != 0) sample = -sample; /* get magnitude */ if (sample > CLIP) sample = CLIP; /* clip the magnitude */ /* Convert from 16 bit linear to ulaw. */ sample = sample + BIAS; exponent = exp_lut[(sample >> 7) & 0xFF]; mantissa = (sample >> (exponent + 3)) & 0x0F; ulawbyte = ~(sign | (exponent << 4) | mantissa); if (ZEROTRAP) if (ulawbyte == 0) ulawbyte = 0x02; /* optional CCITT trap */ if (ulawbyte < 0) ulawbyte += 256; return ulawbyte; } private class RingReader extends InputStream { private AudioStream stream; private RingBufferSA ringBuffer; public RingReader(RingBufferSA rb) { ringBuffer = rb; try { headerPos = 0; stream = new AudioStream(this); } catch (Exception e) { e.printStackTrace(); } } public synchronized boolean play () { AudioPlayer.player.start(stream); return true; } public synchronized boolean pause () { AudioPlayer.player.stop(stream); return true; } public synchronized boolean stop () { AudioPlayer.player.stop(stream); return true; } public int read() throws IOException { int result; if (headerPos < header.length) result = header[headerPos++]; else result = ringBuffer.read(); //System.out.println("read "+result); return result; } } private class RingBufferSA extends RingBuffer { private RingReader reader; private int devicePos; public int nextSeg; public RingBufferSA () { reader = new RingReader (this); devicePos = 0; } protected void startWriteThread () {} public synchronized boolean play () { boolean res; res = super.play(); reader.play(); return res; } public synchronized boolean pause () { boolean res; res = super.pause(); reader.pause(); return res; } public synchronized boolean stop () { boolean res; res = super.stop(); reader.stop(); return res; } public int read () { int ringPos; ringPos = (int)(devicePos * rateDiff) * bps; /* if we don't know the segment total yet, we need * to return -1 now */ if (segTotal == 0) return -1; while (ringPos >= nextSeg) { //System.out.println ("read: devicePos: "+devicePos+" ringPos: "+ringPos+" nextSeg: "+nextSeg); synchronized (this) { clear ((int) (playSeg % segTotal)); playSeg++; notifyAll(); } nextSeg += segSize; } int sample = 0; int ptr = ringPos % buffer.length; for (int j=0; j Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.plugin; import com.fluendo.jst.*; import com.fluendo.utils.*; public class FakeSink extends Sink { protected int preroll (Buffer buf) { System.out.println("received preroll buffer "+buf); return Pad.OK; } protected int render (Buffer buf) { System.out.println("received buffer "+buf); if (buf.object != null) { System.out.println("object "+buf.object); } else { MemUtils.dump (buf.data, 0, buf.length); } return Pad.OK; }; public String getFactoryName () { return "fakesink"; } } cortado-0.6.0/src/com/fluendo/plugin/HTTPSrc.java100644 0 0 26614 11270111317 16713 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.plugin; import java.io.*; import java.net.*; import java.text.MessageFormat; import java.util.Locale; import com.fluendo.jst.*; import com.fluendo.utils.*; public class HTTPSrc extends Element { private String userId; private String password; private String userAgent = "Cortado"; private String urlString; private InputStream input; private long contentLength; private long offset; private long offsetLastMessage = 0; private long skipBytes = 0; private String mime; private Caps outCaps; private boolean discont; private URL documentBase; private boolean microSoft = false; private static final int DEFAULT_READSIZE = 4096; private int readSize = DEFAULT_READSIZE; private Pad srcpad = new Pad(Pad.SRC, "src") { private boolean doSeek (Event event) { boolean result; int format; long position; format = event.parseSeekFormat(); position = event.parseSeekPosition(); if (format == Format.PERCENT && contentLength != -1) { position = position * contentLength / Format.PERCENT_MAX; } else if (format != Format.BYTES) { Debug.log (Debug.WARNING, "can only seek in bytes"); return false; } Debug.log(Debug.DEBUG, this+" flushing"); pushEvent (Event.newFlushStart()); synchronized (streamLock) { Debug.log(Debug.DEBUG, this+" synced"); result = false; try { input = getInputStream (position); if (input != null) result = true; } catch (Exception e) { e.printStackTrace (); } pushEvent (Event.newFlushStop()); if (result) { pushEvent (Event.newNewsegment(false, Format.BYTES, position, contentLength, position)); postMessage (Message.newStreamStatus (this, true, Pad.OK, "restart after seek")); result = startTask("cortado-HTTPSrc-Stream-"+Debug.genId()); } else { postMessage (Message.newError (this, "error: Seek failed")); } } return result; } protected boolean eventFunc (Event event) { boolean res; switch (event.getType()) { case Event.SEEK: res = doSeek(event); break; default: res = super.eventFunc (event); break; } return res; } protected void taskFunc() { int ret; int toRead; long left; // Skip to the target offset if required if (skipBytes > 0) { Debug.info("Skipping " + skipBytes + " input bytes"); try { offset += input.skip(skipBytes); } catch (IOException e) { Debug.error("input.skip error: " + e); postMessage(Message.newError(this, "File read error")); return; } skipBytes = 0; } // Calculate the read size if (contentLength != -1) { if (microSoft) { /* don't read the last byte in microsoft VM, it screws up the socket * completely. */ if (contentLength == 0) left = 0; else left = (contentLength - 1) - offset; } else left = contentLength - offset; } else left = -1; if (left != -1 && left < readSize) toRead = (int) left; else toRead = readSize; // Perform the read Buffer data = Buffer.create(); data.ensureSize (toRead); data.offset = 0; try { if (toRead > 0) { data.length = input.read (data.data, 0, toRead); } else { data.length = -1; } } catch (Exception e) { e.printStackTrace(); data.length = 0; } if (data.length <= 0) { /* EOS */ postMessage (Message.newBytePosition(this, offset)); offsetLastMessage = offset; try { input.close(); } catch (Exception e) { e.printStackTrace(); } data.free(); Debug.log(Debug.INFO, this+" reached EOS"); pushEvent (Event.newEOS()); postMessage (Message.newStreamStatus (this, false, Pad.UNEXPECTED, "reached EOS")); pauseTask(); return; } offset += data.length; if(offsetLastMessage > offset) { offsetLastMessage = 0; } if(offset - offsetLastMessage > contentLength / 100) { postMessage (Message.newBytePosition(this, offset)); offsetLastMessage = offset; } // Negotiate capabilities if (srcpad.getCaps() == null) { String typeMime; typeMime = ElementFactory.typeFindMime (data.data, data.offset, data.length); if (typeMime != null) { if (!typeMime.equals (mime)) { Debug.log(Debug.WARNING, "server contentType: "+mime+" disagrees with our typeFind: " +typeMime); } Debug.log(Debug.INFO, "using typefind contentType: "+typeMime); mime = typeMime; } else { Debug.log(Debug.INFO, "typefind failed, using server contentType: "+mime); } outCaps = new Caps (mime); srcpad.setCaps (outCaps); } data.caps = outCaps; data.setFlag (com.fluendo.jst.Buffer.FLAG_DISCONT, discont); discont = false; // Push the data to the peer if ((ret = push(data)) != OK) { if (isFlowFatal(ret) || ret == Pad.NOT_LINKED) { postMessage (Message.newError (this, "error: "+getFlowName (ret))); pushEvent (Event.newEOS()); } postMessage (Message.newStreamStatus (this, false, ret, "reason: "+getFlowName (ret))); pauseTask(); } } protected boolean activateFunc (int mode) { boolean res = true; switch (mode) { case MODE_NONE: postMessage (Message.newStreamStatus (this, false, Pad.WRONG_STATE, "stopping")); res = stopTask(); input = null; outCaps = null; mime = null; break; case MODE_PUSH: try { contentLength = -1; input = getInputStream(0); if (input == null) res = false; } catch (Exception e) { res = false; } if (res) { postMessage (Message.newStreamStatus (this, true, Pad.OK, "activating")); res = startTask("cortado-HTTPSrc-Stream-"+Debug.genId()); } break; default: res = false; break; } return res; } }; private InputStream openWithConnection(URL url, long offset) throws IOException { InputStream dis = null; URLConnection uc = url.openConnection(); uc.setRequestProperty ("Connection", "Keep-Alive"); String range; if (offset != 0 && contentLength != -1) range = "bytes=" + offset+"-"+(contentLength-1); else if (offset != 0) range = "bytes=" + offset+"-"; else range = null; if (range != null) { Debug.info("doing range: "+range); uc.setRequestProperty ("Range", range); } uc.setRequestProperty ("User-Agent", userAgent); if (userId != null && password != null) { String userPassword = userId + ":" + password; String encoding = Base64Converter.encode (userPassword.getBytes()); uc.setRequestProperty ("Authorization", "Basic " + encoding); } uc.setRequestProperty ("Content-Type","application/octet-stream"); /* This will send the request. */ dis = uc.getInputStream(); String responseRange = uc.getHeaderField("Content-Range"); long responseOffset; if (responseRange == null) { Debug.info("Response contained no Content-Range field, assuming offset=0"); responseOffset = 0; } else { try { MessageFormat format = new MessageFormat("bytes {0,number}-{1,number}"); format.setLocale(Locale.US); java.lang.Object parts[] = format.parse(responseRange); responseOffset = ((Number)parts[0]).longValue(); if (responseOffset < 0) { responseOffset = 0; } Debug.debug("Stream successfully with offset " + responseOffset); } catch (Exception e) { Debug.info("Error parsing Content-Range header"); responseOffset = 0; } } contentLength = uc.getHeaderFieldInt ("Content-Length", -1) + responseOffset; mime = uc.getContentType(); this.offset = responseOffset; if (responseOffset < offset) { this.skipBytes = offset - responseOffset; } else { this.skipBytes = 0; } return dis; } private InputStream getInputStream (long offset) throws Exception { InputStream dis = null; try { URL url; boolean isAbsolute; postMessage(Message.newResource (this, "Opening "+urlString)); Debug.log(Debug.INFO, "reading from url "+urlString); /* IE fails parsing absolute urls in an absolute context; it adds some * random slashes. We workaround this by checking if the urlString is * absolute and avoid the documentBase parsing */ isAbsolute = urlString.startsWith("http://"); if (!isAbsolute && documentBase != null) { Debug.log(Debug.INFO, "parsing in document base"); url = new URL(documentBase, urlString); } else { Debug.log(Debug.INFO, "parsing as absolute URL"); url = new URL(urlString); } Debug.log(Debug.INFO, "trying to open "+url+" at offset "+offset); dis = openWithConnection(url, offset); discont = true; if (contentLength != -1) { postMessage(Message.newDuration (this, Format.BYTES, contentLength)); } Debug.log(Debug.INFO, "opened "+url); Debug.log(Debug.INFO, "contentLength: "+contentLength); Debug.log(Debug.INFO, "server contentType: "+mime); } catch (SecurityException e) { e.printStackTrace(); postMessage(Message.newError (this, "Not allowed "+urlString+"...")); } catch (Exception e) { e.printStackTrace(); postMessage(Message.newError (this, "Failed opening "+urlString+"...")); } catch (Throwable t) { t.printStackTrace(); postMessage(Message.newError (this, "Failed opening "+urlString+"...")); } return dis; } public String getFactoryName () { return "httpsrc"; } public HTTPSrc () { super (); if (System.getProperty("java.vendor").toUpperCase().startsWith ("MICROSOFT", 0)) { Debug.log (Debug.WARNING, "Found MS JVM, work around inputStream EOS bugs."); microSoft = true; } addPad (srcpad); } public synchronized boolean setProperty(String name, java.lang.Object value) { boolean res = true; if (name.equals("url")) { urlString = String.valueOf(value); } else if (name.equals("documentBase")) { documentBase = (URL)value; } else if (name.equals("userId")) { userId = (value == null) ? null : String.valueOf(value); } else if (name.equals("userAgent")) { userAgent = String.valueOf(value); } else if (name.equals("password")) { password = (value == null) ? null : String.valueOf(value); } else if (name.equals("readSize")) { readSize = Integer.parseInt((String)value); } else { res = false; } return res; } } cortado-0.6.0/src/com/fluendo/plugin/JPEGDec.java100644 0 0 10143 11270111317 16613 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.plugin; import java.awt.*; import com.fluendo.jst.*; import com.fluendo.utils.*; public class JPEGDec extends Element { private Toolkit toolkit; private Component component; private MediaTracker mediaTracker; private int width, height; private Pad srcpad = new Pad(Pad.SRC, "src") { protected boolean eventFunc (com.fluendo.jst.Event event) { return sinkpad.pushEvent(event); } }; private Pad sinkpad = new Pad(Pad.SINK, "sink") { protected boolean eventFunc (com.fluendo.jst.Event event) { boolean result; switch (event.getType()) { case com.fluendo.jst.Event.FLUSH_START: result = srcpad.pushEvent (event); synchronized (streamLock) { Debug.log(Debug.INFO, "synced "+this); } break; case com.fluendo.jst.Event.FLUSH_STOP: result = srcpad.pushEvent(event); break; case com.fluendo.jst.Event.EOS: case com.fluendo.jst.Event.NEWSEGMENT: default: result = srcpad.pushEvent(event); break; } return result; } protected int chainFunc (com.fluendo.jst.Buffer buf) { int ret; Image img = null; img = toolkit.createImage(buf.data, buf.offset, buf.length); if (img != null) { int imgWidth, imgHeight; try { mediaTracker.addImage(img, 0); mediaTracker.waitForID(0); mediaTracker.removeImage(img, 0); } catch (Exception e) { e.printStackTrace(); return Pad.ERROR; } imgWidth = img.getWidth(null); imgHeight = img.getHeight(null); if (imgWidth != width || imgHeight != height) { width = imgWidth; height = imgHeight; Debug.log(Debug.INFO, "jpeg frame: "+width+","+height); caps = new Caps ("video/raw"); caps.setFieldInt ("width", width); caps.setFieldInt ("height", height); caps.setFieldInt ("aspect_x", 1); caps.setFieldInt ("aspect_y", 1); } buf.object = img; buf.caps = caps; ret = srcpad.push(buf); } else { System.out.println ("could not decode jpeg image"); Debug.log (Debug.WARNING, "could not decode jpeg image, continueing"); buf.free(); ret = OK; } return ret; } }; public JPEGDec() { super(); toolkit = Toolkit.getDefaultToolkit(); addPad (srcpad); addPad (sinkpad); } protected int changeState (int transition) { int res; switch (transition) { case STOP_PAUSE: width = -1; height = -1; break; default: break; } res = super.changeState (transition); return res; } public boolean setProperty (String name, java.lang.Object value) { if (name.equals("component")) { component = (Component) value; toolkit = component.getToolkit(); mediaTracker = new MediaTracker (component); } else return false; return true; } public java.lang.Object getProperty (String name) { if (name.equals("component")) { return component; } return null; } public String getFactoryName () { return "jpegdec"; } public String getMime () { return "image/jpeg"; } public int typeFind (byte[] data, int offset, int length) { return -1; } } cortado-0.6.0/src/com/fluendo/plugin/KateDec.java100644 0 0 22262 11350725171 16767 0ustar 0 0 /* Copyright (C) <2008> ogg.k.ogg.k * based on code Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.plugin; import java.util.*; import com.jcraft.jogg.*; import com.fluendo.jkate.*; import com.fluendo.jst.*; import com.fluendo.utils.*; /** * Katedec is a decoder element for the Kate stream format. * See http://wiki.xiph.org/index.php/OggKate for more information. * Kate streams may be multiplexed in Ogg. * The Katedec element accepts Kate packets (presumably demultiplexed by an * Ogg demuxer element) on its sink, and generates Kate events on its source. * Kate events are Kate specific structures, which may then be interpreted * by a renderer. */ public class KateDec extends Element implements OggPayload { /* Kate magic: 0x80 (BOS header) followed by "kate\0\0\0" */ private static final byte[] signature = { -128, 0x6b, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00 }; private Info ki; private Comment kc; private State k; private Packet op; private int packetno; private long basetime = 0; private long lastTs; private boolean haveBOS = false; private boolean haveDecoder = false; /* * OggPayload interface */ public boolean isType (Packet op) { return typeFind (op.packet_base, op.packet, op.bytes) > 0; } public boolean isKeyFrame (Packet op) { return true; } /** * A discontinuous codec will not cause the pipeline to wait for data if starving */ public boolean isDiscontinuous () { return true; } public int takeHeader (Packet op) { int ret = ki.decodeHeader(kc, op); if (ret >= 0) { haveBOS = true; } if (ret > 0) { k.decodeInit(ki); Debug.debug("Kate decoder ready"); haveDecoder = true; } return ret; } public boolean isHeader (Packet op) { return (op.packet_base[op.packet] & 0x80) == 0x80; } public long getFirstTs (Vector packets) { int len = packets.size(); int i; long time; com.fluendo.jst.Buffer data = null; /* first find buffer with valid offset */ for (i=0; i 0) { // we've decoded all headers Debug.log(Debug.DEBUG, "Kate initialized for decoding"); /* we're sending raw kate_event structures */ caps = new Caps ("application/x-kate-event"); } buf.free(); packetno++; return OK; } else { if ((op.packet_base[op.packet] & 0x80) == 0x80) { Debug.log(Debug.DEBUG, "ignoring header"); buf.free(); return OK; } if (timestamp != -1) { lastTs = timestamp; } if (true) { try{ result = k.decodePacketin(op); if (result < 0) { buf.free(); Debug.log(Debug.ERROR, "Error Decoding Kate."); postMessage (Message.newError (this, "Error decoding Kate")); return ERROR; } com.fluendo.jkate.Event ev = k.decodeEventOut(); if (ev != null) { buf.object = ev; buf.caps = caps; buf.timestamp = granuleToDuration(ev.start); buf.timestampEnd = buf.timestamp + granuleToDuration(ev.duration); Debug.log( Debug.DEBUG, parent.getName() + " >>> " + buf ); Debug.debug("Got Kate text: "+new String(ev.text)+" from "+buf.timestamp+" to "+buf.timestampEnd+", basetime "+basetime); result = srcPad.push(buf); Debug.log(Debug.DEBUG, "push returned "+result); } else { Debug.debug("Got no event"); buf.free(); result = OK; } } catch (Exception e) { e.printStackTrace(); postMessage (Message.newError (this, e.getMessage())); result = ERROR; } } else { result = OK; buf.free(); } } packetno++; return result; } protected boolean activateFunc (int mode) { return true; } }; public KateDec() { super(); ki = new Info(); kc = new Comment(); k = new State(); op = new Packet(); addPad (srcPad); addPad (sinkPad); } protected int changeState (int transition) { int res; switch (transition) { case STOP_PAUSE: lastTs = -1; packetno = 0; break; default: break; } res = super.changeState (transition); switch (transition) { case PAUSE_STOP: ki.clear(); kc.clear(); k.clear(); break; default: break; } return res; } public java.lang.Object getProperty (String name) { if (name.equals("language")) { return ki.language; } else if (name.equals("category")) { return ki.category; } else { return super.getProperty(name); } } public String getFactoryName () { return "katedec"; } public String getMime () { return "application/x-kate"; } public String getMime (Packet op) { Info ki = new Info(); Comment kc = new Comment(); if (!isType(op)) return null; int ret = ki.decodeHeader(kc, op); if (ret < 0) return null; String mime = "application/x-kate"; if (!ki.language.equals("")) mime += ";language="+ki.language; if (!ki.category.equals("")) mime += ";category="+ki.category; return mime; } public int typeFind (byte[] data, int offset, int length) { if (MemUtils.startsWith (data, offset, length, signature)) return 10; return -1; } } cortado-0.6.0/src/com/fluendo/plugin/KateOverlay.java100644 0 0 11303 11350725171 17707 0ustar 0 0 /* Copyright (C) <2008> ogg.k.ogg.k * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.plugin; import java.awt.*; import java.awt.image.*; import com.fluendo.jst.*; import com.fluendo.jtiger.Renderer; import com.fluendo.utils.*; /* This element renders a Kate stream on incoming video */ public class KateOverlay extends Overlay { private Font font = null; private String text = null; private Renderer tr = new Renderer(); private Dimension image_dimension = null; private Pad kateSinkPad = new Pad(Pad.SINK, "katesink") { protected boolean eventFunc (com.fluendo.jst.Event event) { /* don't propagate, the video sink is the master */ switch (event.getType()) { case com.fluendo.jst.Event.FLUSH_START: case com.fluendo.jst.Event.FLUSH_STOP: case com.fluendo.jst.Event.NEWSEGMENT: onFlush(); break; default: break; } return true; } /** * This pad receives Kate events, and add them to the renderer. * They will be removed from it as they become inactive. */ protected synchronized int chainFunc (com.fluendo.jst.Buffer buf) { addKateEvent((com.fluendo.jkate.Event)buf.object); return Pad.OK; } }; /** * Create a new Kate overlay */ public KateOverlay() { super(); addPad(kateSinkPad); } /** * Add a new Kate event to the renderer. * This needs locking so the Kate events are not changed while the * overlay is rendering them to an image. */ protected synchronized void addKateEvent(com.fluendo.jkate.Event ev) { tr.add(ev); Debug.log(Debug.DEBUG, "Kate overlay got Kate event: "+new String(ev.text)); } /** * Upon a flushing event, remove any existing event, now obsolete. * This needs locking so the Kate events are not changed while the * overlay is rendering them to an image. */ protected synchronized void onFlush() { tr.flush(); image_dimension = null; Debug.log(Debug.DEBUG, "Kate overlay flushing"); } protected Image getImage(com.fluendo.jst.Buffer buf) { Image img; if (buf.object instanceof ImageProducer) { img = component.createImage((ImageProducer)buf.object); } else if (buf.object instanceof Image) { img = (Image)buf.object; } else { System.out.println(this+": unknown buffer received "+buf); img = null; } return img; } /** * Overlay the Kate renderer onto the given image. */ protected synchronized void overlay(com.fluendo.jst.Buffer buf) { Image img = null; if (image_dimension == null) { img = getImage(buf); if (img == null) { return; } image_dimension = new Dimension(img.getWidth(null), img.getHeight(null)); } /* before rendering, we update the state of the events; for now this just weeds out old ones, but at some point motions could be tracked. */ int ret = tr.update(component, image_dimension, buf.timestamp/(double)Clock.SECOND); if (ret < 0) { Debug.log(Debug.WARNING, "Failed to update jtiger renderer"); return; } /* if the renderer is empty and the buffer is not a duplicate, we leave the video alone */ if (!buf.duplicate && ret > 0) { Debug.log(Debug.DEBUG, "Video frame is not a dupe and we have nothing to overlay."); return; } /* if the renderer isn't dirty and the image hasn't changed, we don't need to do anything, as the result image would be the same */ if (buf.duplicate && !tr.isDirty()) { Debug.log(Debug.DEBUG, "Video frame is a dupe and we're not dirty. Yeah."); return; } /* render Kate stream on top */ if (img == null) { img = getImage(buf); } img = tr.render(component, img); /* We need to draw a new overlay, so we need to get the buffer to update, as it might have a previous overlay on top of it */ buf.duplicate = false; buf.object = img; } public String getFactoryName () { return "kateoverlay"; } } cortado-0.6.0/src/com/fluendo/plugin/MulawDec.java100644 0 0 5046 11270111317 17141 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.plugin; import com.fluendo.jst.*; import com.fluendo.utils.*; public class MulawDec extends Element { private int rate, channels; private Pad srcPad = new Pad(Pad.SRC, "src") { protected boolean eventFunc (com.fluendo.jst.Event event) { return sinkPad.pushEvent(event); } }; private Pad sinkPad = new Pad(Pad.SINK, "sink") { protected boolean eventFunc (com.fluendo.jst.Event event) { boolean result; switch (event.getType()) { case com.fluendo.jst.Event.FLUSH_START: result = srcPad.pushEvent (event); synchronized (streamLock) { Debug.log(Debug.INFO, "synced "+this); } break; case com.fluendo.jst.Event.FLUSH_STOP: result = srcPad.pushEvent(event); break; case com.fluendo.jst.Event.EOS: case com.fluendo.jst.Event.NEWSEGMENT: default: result = srcPad.pushEvent(event); break; } return result; } protected int chainFunc (com.fluendo.jst.Buffer buf) { int ret; if (caps == null) { Debug.log(Debug.INFO, "mulaw: rate: "+rate); Debug.log(Debug.INFO, "mulaw: channels: "+channels); caps = new Caps ("audio/x-mulaw"); caps.setFieldInt ("rate", rate); caps.setFieldInt ("channels", channels); } buf.caps = caps; ret = srcPad.push(buf); return ret; } }; public MulawDec() { super(); rate = 8000; channels = 1; addPad (srcPad); addPad (sinkPad); } public String getFactoryName () { return "mulawdec"; } public String getMime () { return "audio/x-mulaw"; } public int typeFind (byte[] data, int offset, int length) { return -1; } } cortado-0.6.0/src/com/fluendo/plugin/MultipartDemux.java100644 0 0 27330 11270111317 20444 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.plugin; import java.util.*; import com.fluendo.jst.*; import com.fluendo.utils.*; public class MultipartDemux extends Element { private static final String MIME = "multipart/x-mixed-replace"; private static final String DEFAULT_BOUNDARY = "--ThisRandomString"; private Vector streams; private byte[] accum; private int accumSize; private int accumPos; private int dataEnd; private static final int STATE_FIND_BOUNDARY = 1; private static final int STATE_PARSE_HEADERS = 2; private static final int STATE_FIND_DATA_END = 3; private int state = STATE_FIND_BOUNDARY; private String boundaryString = DEFAULT_BOUNDARY; private byte[] boundary = boundaryString.getBytes(); private int boundaryLen = boundary.length; private static final byte[] headerEnd = "\n".getBytes(); private static final int headerEndLen = headerEnd.length; private static final String contentType = "content-type: "; private static final int contentTypeLen = contentType.length(); private MultipartStream currentStream = null; class MultipartStream extends Pad { private String mimeType; public MultipartStream(String mime) { super(Pad.SRC, "src_" + mime); mimeType = mime; caps = new Caps(mime); } protected boolean eventFunc(com.fluendo.jst.Event event) { return sinkpad.pushEvent(event); } } private Pad sinkpad = new Pad(Pad.SINK, "sink") { protected boolean setCapsFunc(Caps caps) { String mime = caps.getMime(); String capsBoundary; if (!mime.equals(MIME)) { postMessage(Message.newError(this, "expected \"" + mime + "\", got \"" + mime + "\"")); return false; } capsBoundary = caps.getFieldString("boundary", DEFAULT_BOUNDARY); Debug.log(Debug.INFO, this + " boundary string: \"" + capsBoundary + "\""); boundaryString = capsBoundary + "\n"; boundary = boundaryString.getBytes(); boundaryLen = boundary.length; return true; } private MultipartStream findStream(String mime) { MultipartStream stream = null; for (int i = 0; i < streams.size(); i++) { stream = (MultipartStream) streams.elementAt(i); if (stream.mimeType.equals(mime)) break; stream = null; } return stream; } private boolean forwardEvent(com.fluendo.jst.Event event) { for (int i = 0; i < streams.size(); i++) { MultipartStream stream = (MultipartStream) streams.elementAt(i); stream.pushEvent(event); } return true; } protected boolean eventFunc(com.fluendo.jst.Event event) { switch (event.getType()) { case Event.FLUSH_START: forwardEvent(event); synchronized (streamLock) { Debug.log(Debug.INFO, "synced " + this); } break; case Event.NEWSEGMENT: case Event.FLUSH_STOP: case Event.EOS: synchronized (streamLock) { forwardEvent(event); } break; default: forwardEvent(event); break; } return true; } /* * copy the buffer data into our buffer. If we need to enlarge the * buffer, we can flush out any skipped bytes */ private void accumulateBuffer(com.fluendo.jst.Buffer buf) { int lastPos = accumSize + accumPos; /* make room */ if (accum.length < lastPos + buf.length) { byte[] newAcum; /* * FIXME, check if we need a bigger buffer or if we can just * shrink the current one */ newAcum = new byte[accum.length + buf.length]; System.arraycopy(accum, accumPos, newAcum, 0, accumSize); accum = newAcum; accumPos = 0; lastPos = accumSize; } System.arraycopy(buf.data, buf.offset, accum, lastPos, buf.length); accumSize += buf.length; // System.out.println("added "+buf.length+" pos "+accumPos+" size // "+accumSize); } private void flushBytes(int bytes) { accumPos += bytes; accumSize -= bytes; // System.out.println("flushing "+bytes+" pos "+accumPos+" size // "+accumSize); } /* * find bytes of consecutive bytes in the buffer. This function returns * the position in the buffer where the bytes were found or -1 if the * bytes were not found. */ private int findBytes(int startPos, byte[] bytes, int bytesLen) { /* * startPos is the first byte in the buffer where we should start * scanning. */ int scanPos = startPos; /* we always start comparing the first byte of the bytes */ int pos = 0; int size = accumSize; // System.out.println("findBytes: size:"+size+" "+bytesLen); /* while we have enough data to compare */ while (size > bytesLen) { /* check if we have a match */ if (accum[scanPos] == bytes[pos]) { // System.out.println("match: scanPos:"+scanPos+" // "+accum[scanPos]+" pos:"+pos+" "+bytes[pos]); /* position to compare the next byte */ pos++; if (pos == bytesLen) { /* * we found all consecutive bytes, we have a complete * match */ return startPos; } } else { /* * we have no match, flush our buffer to next byte and start * scanning for the first byte in the bytes string again. * The data size decrements. */ // System.out.println("fail: scanPos:"+scanPos+" // "+accum[scanPos]+" pos:"+pos+" "+bytes[pos]); scanPos -= pos; size += pos; startPos = scanPos + 1; pos = 0; } /* move to next byte */ scanPos++; size--; } return -1; } /* * find boundary bytes of consecutive bytes in the buffer. This function * returns true if the bytes where found with the accumPos position * pointing to the byte in the buffer. */ private boolean findBoundary() { int pos = findBytes(accumPos, boundary, boundaryLen); if (pos != -1) { flushBytes(pos - accumPos); // System.out.println("buffer now: sync at "+accumPos); } return pos != -1; } /* * read the headers up to the first \n\n sequence. we store the * Content-Type: header in lastContentType */ private boolean parseHeaders() { int headerStart = accumPos; int prevHdr; while (true) { prevHdr = headerStart; int pos = findBytes(headerStart, headerEnd, headerEndLen); if (pos == -1) return false; if (pos == prevHdr) { /* all headers parsed */ flushBytes(pos + 1 - accumPos); return true; } String header = new String(accum, headerStart, pos - headerStart); header = header.toLowerCase(); if (header.startsWith(contentType)) { String mime = header.substring(contentTypeLen).trim(); currentStream = findStream(mime); if (currentStream == null) { currentStream = new MultipartStream(mime); streams.addElement(currentStream); addPad(currentStream); } } /* go to next header */ headerStart = pos + 1; } } private boolean findDataEnd() { int pos = findBytes(accumPos, boundary, boundaryLen); // System.out.println("find data end "+accumPos+" size "+accumSize+" // pos "+pos); if (pos != -1) { dataEnd = pos - 1; } return pos != -1; } protected int chainFunc(com.fluendo.jst.Buffer buf) { int flowRet = OK; // System.out.println("input"); // MemUtils.dump (buf.data, buf.offset, buf.length); accumulateBuffer(buf); buf.free(); switch (state) { case STATE_FIND_BOUNDARY: if (!findBoundary()) break; /* skip boundary */ flushBytes(boundary.length); state = STATE_PARSE_HEADERS; /* fallthrough */ case STATE_PARSE_HEADERS: if (!parseHeaders()) break; state = STATE_FIND_DATA_END; /* fallthrough */ case STATE_FIND_DATA_END: if (!findDataEnd()) break; com.fluendo.jst.Buffer data = com.fluendo.jst.Buffer.create(); int dataSize = dataEnd - accumPos; // System.out.println("dataSize: "+dataSize); // MemUtils.dump (accum, accumPos, dataSize); data.copyData(accum, accumPos, dataSize); data.time_offset = -1; data.timestamp = -1; /* skip data */ flushBytes(dataSize); /* and push */ flowRet = currentStream.push(data); state = STATE_FIND_BOUNDARY; break; default: flowRet = ERROR; break; } // System.out.println("return "+flowRet); return flowRet; } }; public String getFactoryName() { return "multipartdemux"; } public String getMime() { return MIME; } public int typeFind(byte[] data, int offset, int length) { return -1; } public MultipartDemux() { super(); accum = new byte[8192]; accumSize = 0; accumPos = 0; streams = new Vector(); addPad(sinkpad); } } cortado-0.6.0/src/com/fluendo/plugin/OggDemux.java100644 0 0 41162 11350725171 17206 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.plugin; import java.util.*; import com.jcraft.jogg.*; import com.fluendo.jst.*; import com.fluendo.utils.*; public class OggDemux extends Element { private SyncState oy; private OggChain chain; private Page og; private Packet op; private static final byte[] signature = { 0x4f, 0x67, 0x67, 0x53 }; private static final byte[] fishead_signature = { 0x66, 0x69, 0x73, 0x68, 0x65, 0x61, 0x64}; private static final byte[] cmml_signature = {0x43, 0x4d, 0x4d, 0x4c}; private static final int TYPE_NEW = 0; private static final int TYPE_UNKNOWN = 1; private static final int TYPE_SKELETON = 2; private static final int TYPE_CMML = 3; private static final int TYPE_MEDIA = 4; private static final String payload_names[] = { "TheoraDec", "VorbisDec", "KateDec" }; private OggPayload payloads[] = { null, null, null }; class OggStream extends Pad { public int serialno; public StreamState os; private Vector headers; private long baseTs; public boolean haveHeaders; public Vector queue; public boolean started; public boolean complete; public boolean discont; public boolean active; public boolean haveKeyframe; public boolean sentHeaders; public int type; public int lastRet; private OggPayload payload; public OggStream (int serial) { super (Pad.SRC, "serial_"+serial); serialno = serial; os = new StreamState(); os.init(serial); os.reset(); queue = new Vector(); headers = new Vector(); haveHeaders = false; haveKeyframe = false; payload = null; discont = true; complete = false; started = false; baseTs = -1; lastRet = OK; } public void markDiscont () { discont = true; complete = false; haveKeyframe = false; started = false; } public void reset () { markDiscont(); os.reset(); lastRet = OK; } public boolean isComplete () { return complete; } public void activate() { if (active) return; sentHeaders = false; lastRet = OK; addPad(this); active = true; } public void deActivate() { if (!active) return; removePad(this); pushEvent (Event.newEOS()); active = false; } public void reStart(long firstTs) { com.fluendo.jst.Buffer buf; long time; if (!active) return; baseTs = firstTs; time = firstTs - baseTs; Debug.log(Debug.DEBUG, this+" pushing segment start "+firstTs+", time "+time); pushEvent (Event.newNewsegment (false, Format.TIME, firstTs, -1, time)); if (!sentHeaders) { for (int i=0; i 0) { haveHeaders = true; } } else { haveHeaders = true; } } /* if we have all the headers we can stream */ if (haveHeaders) { /* discontinuous codecs do not need to wait for data to allow playback */ if (!complete && payload.isDiscontinuous()) { complete = true; } if (complete && started) { int ret; com.fluendo.jst.Buffer data = bufferFromPacket (op); ret = push (data); return combineFlows (this, ret); } if (haveKeyframe || payload.isKeyFrame(op)) { com.fluendo.jst.Buffer data = bufferFromPacket (op); queue.addElement (data); haveKeyframe = true; if (op.granulepos != -1) { complete = true; } } } return Pad.OK; } public int pushPage (Page og) { int res; int flowRet = Pad.OK; res = os.pagein(og); if (res < 0) { // error; stream version mismatch perhaps System.err.println("Error reading first page of Ogg bitstream data."); postMessage (Message.newError (this, "Error reading first page of Ogg bitstream data.")); return ERROR; } while (flowRet == OK) { res = os.packetout(op); if(res == 0) break; // need more data if(res == -1) { // missing or corrupt data at this page position // no reason to complain; already complained above Debug.log(Debug.WARNING, "ogg error: packetout gave "+res); discont = true; } else { flowRet = pushPacket(op); } } return flowRet; } protected boolean eventFunc (com.fluendo.jst.Event event) { return sinkPad.pushEvent (event); } } class OggChain { private Vector streams; private boolean active; private boolean synced; private long firstTs; public OggChain () { streams = new Vector(); synced = false; active = false; firstTs = -1; } public boolean isActive() { return active; } public void activate() { if (active) return; Debug.log(Debug.DEBUG, "activating chain"); for (int i=0; i Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.plugin; import java.util.*; import com.jcraft.jogg.*; public interface OggPayload { /** * Check if the packet contains the signature * of the payload. */ public boolean isType (Packet op); /** * Initialize the payload with a header packet. * Returns < 0 for error, 0 if OK, 1 if OK and ready for decoding data. */ public int takeHeader (Packet op); /** * Check if the packet contains a header packet */ public boolean isHeader (Packet op); /** * Check if the packet contains a keyframe */ public boolean isKeyFrame (Packet op); /** * Get the first timestamp of the list of packets */ public long getFirstTs (Vector packets); /** * Convert the granule pos to a timestamp */ public long granuleToTime (long gp); /** * Get mime type */ public String getMime (); /** * Get mime type from the given packet */ public String getMime (Packet op); /** * Check if the stream is discontinuous (eg, no need to wait * for data on this stream before playing) */ public boolean isDiscontinuous (); } cortado-0.6.0/src/com/fluendo/plugin/Overlay.java100644 0 0 6654 11274615664 17111 0ustar 0 0 /* Copyright (C) <2008> ogg.k.ogg.k * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.plugin; import java.awt.*; import com.fluendo.jst.*; import com.fluendo.utils.*; /** * This is a base overlay element, just passes images from sink to source. * Extend this and override the overlay function to draw something onto * images as they go from sink to source. */ public class Overlay extends Element { protected Component component; private Pad videoSrcPad = new Pad(Pad.SRC, "videosrc") { protected boolean eventFunc (com.fluendo.jst.Event event) { return videoSinkPad.pushEvent(event); } }; private Pad videoSinkPad = new Pad(Pad.SINK, "videosink") { protected boolean eventFunc (com.fluendo.jst.Event event) { return videoSrcPad.pushEvent (event); } /** * Receives an image, allows a derived class to overlay whatever it wants on it, * and sends it to the video source pad. */ protected int chainFunc (com.fluendo.jst.Buffer buf) { int result; Debug.log( Debug.DEBUG, parent.getName() + " <<< " + buf ); overlay(buf); result = videoSrcPad.push(buf); if (result != Pad.OK) { Debug.log( Debug.WARNING, parent.getName() + ": failed to push buffer to video source pad: "+result); } return result; } protected boolean activateFunc (int mode) { return true; } }; public Overlay() { super(); addPad (videoSinkPad); addPad (videoSrcPad); } /** * this function may be overridden to draw whatever the derived * class wants onto the incoming image. * By default, the image is passed without alteration. */ protected void overlay(com.fluendo.jst.Buffer buf) { /* straight pass through by default */ } public boolean setProperty (String name, java.lang.Object value) { if (name.equals("component")) { component = (Component) value; } else { return super.setProperty(name, value); } return true; } public java.lang.Object getProperty (String name) { if (name.equals("component")) { return component; } else { return super.getProperty(name); } } /* from the video sink code, I do not understand what this does semantically, the frame would be 0x0 sized. Maybe just to avoid possible null dereference, but I suspect there might be something more clever, so it goes in for safety */ protected int changeState (int transition) { if (currentState == STOP && pendingState == PAUSE && component == null) { Frame frame = new Frame(); component = (Component) frame; } return super.changeState(transition); } public String getFactoryName () { return "overlay"; } } cortado-0.6.0/src/com/fluendo/plugin/Queue.java100644 0 0 25001 11274340315 16543 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.plugin; import java.util.*; import com.fluendo.jst.*; import com.fluendo.utils.*; public class Queue extends Element { /* leaky types */ public static final int NO_LEAK = 0; public static final int LEAK_UPSTREAM = 1; public static final int LEAK_DOWNSTREAM = 2; private static final int DEFAULT_MAX_BUFFERS = 100; private static final int DEFAULT_MAX_SIZE = -1; private static final boolean DEFAULT_IS_BUFFER = false; private static final int DEFAULT_LOW_PERCENT = 10; private static final int DEFAULT_HIGH_PERCENT = 70; private static final int DEFAULT_LEAKY = NO_LEAK; private Vector queue = new Vector(); private int srcResult = Pad.WRONG_STATE; private int size; private boolean isBuffering; private boolean isEOS; private boolean headNeedsDiscont = false; private boolean tailNeedsDiscont = false; private int maxBuffers = DEFAULT_MAX_BUFFERS; private int maxSize = DEFAULT_MAX_SIZE; private boolean isBuffer = DEFAULT_IS_BUFFER; private int lowPercent = DEFAULT_LOW_PERCENT; private int highPercent = DEFAULT_HIGH_PERCENT; private int leaky = DEFAULT_LEAKY; private boolean isFilled() { if (maxSize != -1) { return size >= maxSize; } else { return queue.size() >= maxBuffers; } } private boolean isEmpty() { return queue.size() == 0; } private void clearQueue () { for (Enumeration e = queue.elements(); e.hasMoreElements();) { java.lang.Object obj = e.nextElement(); if (obj instanceof Buffer) ((Buffer)obj).free(); } queue.setSize(0); size = 0; isBuffering = true; } private void updateBuffering () { if (!isBuffer || srcResult != Pad.OK) return; if (isEOS) { if (isBuffering) { isBuffering = false; postMessage(Message.newBuffering(this, false, 0)); } return; } /* figure out the percentage we are filled */ int percent = size * 100 / maxSize; if (percent > 100) percent = 100; if (isBuffering) { if (percent >= highPercent) { isBuffering = false; } postMessage (Message.newBuffering (this, isBuffering, percent)); } else { if (percent < lowPercent) { isBuffering = true; } } } private void leakDownstream () { /* for as long as the queue is filled, dequeue an item and discard it */ java.lang.Object leak; while (isFilled()) { synchronized (queue) { leak = queue.lastElement(); if (leak == null) { Debug.error("There is nothing to dequeue and the queue is still filled. This should not happen."); } queue.removeElementAt(queue.size()-1); if (leak instanceof Buffer) ((Buffer)leak).free(); headNeedsDiscont = true; queue.notifyAll(); } } } private Pad srcpad = new Pad(Pad.SRC, "src") { protected void taskFunc() { java.lang.Object obj; int res; synchronized (queue) { if (srcResult != OK) return; while (isEmpty()) { try { queue.wait(); if (srcResult != OK) return; } catch (InterruptedException ie) {} } obj = queue.elementAt(queue.size()-1); queue.removeElement(obj); queue.notifyAll(); } if (obj instanceof Event) { Event event = (Event) obj; pushEvent(event); res = OK; if (event.getType() == Event.EOS) { postMessage (Message.newStreamStatus (this, false, OK, "flow stopped, EOS")); pauseTask(); } } else { Buffer buf = (Buffer) obj; if (headNeedsDiscont) { buf.setFlag(Buffer.FLAG_DISCONT, true); headNeedsDiscont = false; } size -= buf.length; Debug.log( Debug.DEBUG, parent.getName() + " >>> " + buf ); res = push(buf); if ( maxSize == -1 ) { Debug.log( Debug.DEBUG, parent.getName() + " count = " + queue.size() + "/" + maxBuffers ); } else { Debug.log( Debug.DEBUG, parent.getName() + " size = " + size + "/" + maxSize ); } } synchronized (queue) { if (res != OK) { srcResult = res; if (isFlowFatal (res)) { pushEvent(Event.newEOS()); } postMessage (Message.newStreamStatus (this, false, res, "flow stopped")); pauseTask(); } updateBuffering (); } } protected boolean activateFunc (int mode) { boolean res = true; switch (mode) { case MODE_NONE: synchronized (queue) { clearQueue(); srcResult = WRONG_STATE; queue.notifyAll(); } // Cancel buffering status if (isBuffer && isBuffering) { isBuffering = false; postMessage(Message.newBuffering(this, false, 0)); } postMessage (Message.newStreamStatus (this, false, Pad.WRONG_STATE, "stopping")); res = stopTask(); break; case MODE_PUSH: isEOS = false; synchronized (queue) { srcResult = OK; /* if we buffer, we start when we are hitting the * high watermark */ if (!isBuffer) { isBuffering = false; } else { isBuffering = true; postMessage (Message.newBuffering (this, true, 0)); } postMessage (Message.newStreamStatus (this, true, Pad.OK, "activating")); res = startTask("cortado-Queue-Stream-"+Debug.genId()); } break; default: synchronized (queue) { srcResult = WRONG_STATE; } res = false; break; } return res; } }; private Pad sinkpad = new Pad(Pad.SINK, "sink") { protected boolean eventFunc (Event event) { int type = event.getType(); boolean doQueue = true; switch (type) { case Event.FLUSH_START: srcpad.pushEvent (event); synchronized (queue) { srcResult = WRONG_STATE; queue.notifyAll(); } synchronized (streamLock) { Debug.log(Debug.DEBUG, this+" synced"); } postMessage (Message.newStreamStatus (srcpad, false, Pad.WRONG_STATE, "flush start")); srcpad.pauseTask(); doQueue = false; break; case Event.FLUSH_STOP: srcpad.pushEvent (event); isEOS = false; synchronized (queue) { clearQueue (); srcResult = OK; queue.notifyAll(); } if (isBuffer) { isBuffering = true; postMessage (Message.newBuffering (this, true, 0)); } postMessage (Message.newStreamStatus (srcpad, true, Pad.OK, "restart after flush")); srcpad.startTask("cortado-Queue-Stream-"+Debug.genId()); doQueue = false; break; case Event.EOS: isEOS = true; Debug.log(Debug.INFO, "got EOS: "+this); if (isBuffer) { if (isBuffering) { isBuffering = false; postMessage (Message.newBuffering (this, isBuffering, 100)); } } break; case Event.NEWSEGMENT: default: break; } if (doQueue) { synchronized (queue) { queue.insertElementAt(event, 0); queue.notifyAll(); } } return true; } protected int chainFunc (Buffer buf) { synchronized (queue) { if (srcResult != OK) { buf.free(); return srcResult; } while (isFilled()) { switch (leaky) { case LEAK_UPSTREAM: tailNeedsDiscont = true; Debug.debug(parent.getName() + "is full, leaking buffer on upstream end"); buf.free(); queue.notifyAll(); return OK; case LEAK_DOWNSTREAM: leakDownstream(); break; default: Debug.warn("Unknown leaky type, using default"); /* fall-through */ case NO_LEAK: try { Debug.debug(parent.getName() + " full, waiting..."); queue.wait(); if (srcResult != OK) { buf.free(); return srcResult; } } catch (InterruptedException ie) { ie.printStackTrace(); buf.free(); return WRONG_STATE; } break; } } if (tailNeedsDiscont) { buf.setFlag(Buffer.FLAG_DISCONT, true); tailNeedsDiscont = false; } size += buf.length; updateBuffering(); Debug.log( Debug.DEBUG, parent.getName() + " <<< " + buf ); queue.insertElementAt(buf, 0); if ( maxSize == -1 ) { Debug.log( Debug.DEBUG, parent.getName() + " count = " + queue.size() + "/" + maxBuffers ); } else { Debug.log( Debug.DEBUG, parent.getName() + " size = " + size + "/" + maxSize ); } queue.notifyAll(); } return OK; } }; public Queue() { super(); addPad (srcpad); addPad (sinkpad); } public String getFactoryName() { return "queue"; } public boolean setProperty (String name, java.lang.Object value) { if (name.equals("maxBuffers")) maxBuffers = Integer.valueOf(value.toString()).intValue(); else if (name.equals("maxSize")) maxSize = Integer.valueOf(value.toString()).intValue(); else if (name.equals("isBuffer")) isBuffer = String.valueOf(value).equalsIgnoreCase("true"); else if (name.equals("lowPercent")) lowPercent = Integer.valueOf(value.toString()).intValue(); else if (name.equals("highPercent")) highPercent = Integer.valueOf(value.toString()).intValue(); else if (name.equals("leaky")) leaky = Integer.valueOf(value.toString()).intValue(); else return false; return true; } public java.lang.Object getProperty (String name) { if (name.equals("maxBuffers")) return new Integer (maxBuffers); else if (name.equals("maxSize")) return new Integer (maxSize); else if (name.equals("isBuffer")) return (isBuffer ? "true" : "false"); else if (name.equals("lowPercent")) return new Integer (lowPercent); else if (name.equals("highPercent")) return new Integer (highPercent); else if (name.equals("leaky")) return new Integer (leaky); return null; } } cortado-0.6.0/src/com/fluendo/plugin/Selector.java100644 0 0 7403 11350725171 17227 0ustar 0 0 /* Copyright (C) <2008> ogg.k.ogg.k * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.plugin; import java.util.*; import com.fluendo.jst.*; import com.fluendo.utils.*; /** * This element receives data from N sinks, and selects one of them * to send from its source. */ public class Selector extends Element { private Vector sinks = new Vector(); int selected = -1; Pad selectedPad = null; private Pad srcPad = new Pad(Pad.SRC, "src") { /** * Pushes the event to every sink. */ protected boolean eventFunc (com.fluendo.jst.Event event) { boolean ret = true; for (int n=0; n= sinks.size()) { selected = -1; selectedPad = null; } else { selected = new_selected; selectedPad = (Pad)sinks.elementAt(selected); } srcPad.pushEvent (Event.newFlushStop()); } } else { return super.setProperty(name, value); } return true; } public java.lang.Object getProperty (String name) { if (name.equals("selected")) { return new Integer(selected); } else { return super.getProperty(name); } } public String getFactoryName () { return "selector"; } } cortado-0.6.0/src/com/fluendo/plugin/SmokeDec.java100644 0 0 7207 11270111317 17133 0ustar 0 0 /* Smoke Codec * Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.plugin; import java.awt.*; import com.fluendo.codecs.*; import com.fluendo.jst.*; import com.fluendo.utils.*; public class SmokeDec extends Element { private Component component; private MediaTracker mediaTracker; private SmokeCodec smoke; private int width, height; private Pad srcPad = new Pad(Pad.SRC, "src") { protected boolean eventFunc (com.fluendo.jst.Event event) { return sinkPad.pushEvent(event); } }; private Pad sinkPad = new Pad(Pad.SINK, "sink") { protected boolean eventFunc (com.fluendo.jst.Event event) { boolean result; switch (event.getType()) { case com.fluendo.jst.Event.FLUSH_START: result = srcPad.pushEvent (event); synchronized (streamLock) { Debug.log(Debug.INFO, "synced "+this); } break; case com.fluendo.jst.Event.FLUSH_STOP: result = srcPad.pushEvent(event); break; case com.fluendo.jst.Event.EOS: case com.fluendo.jst.Event.NEWSEGMENT: default: result = srcPad.pushEvent(event); break; } return result; } protected int chainFunc (com.fluendo.jst.Buffer buf) { int ret; Image img = null; img = smoke.decode(buf.data, buf.offset, buf.length); if (img != null) { if (img.getWidth(null) != width || img.getHeight(null) != height) { width = img.getWidth(null); height = img.getHeight(null); Debug.log(Debug.INFO, "smoke frame: "+width+","+height); caps = new Caps ("video/raw"); caps.setFieldInt ("width", width); caps.setFieldInt ("height", height); caps.setFieldInt ("aspect_x", 1); caps.setFieldInt ("aspect_y", 1); } buf.object = img; buf.caps = caps; ret = srcPad.push(buf); } else { if ((smoke.flags & SmokeCodec.KEYFRAME) != 0) { Debug.log (Debug.WARNING, "could not decode jpeg image"); } buf.free(); ret = OK; } return ret; } }; public SmokeDec() { super(); addPad(srcPad); addPad(sinkPad); } public boolean setProperty (String name, java.lang.Object value) { if (name.equals("component")) { component = (Component) value; mediaTracker = new MediaTracker (component); smoke = new SmokeCodec (component, mediaTracker); } else return false; return true; } public java.lang.Object getProperty (String name) { if (name.equals("component")) { return component; } return null; } public String getFactoryName () { return "smokedec"; } public String getMime () { return "video/x-smoke"; } public int typeFind (byte[] data, int offset, int length) { if (data[offset+1] == 0x73) { return 10; } return -1; } } cortado-0.6.0/src/com/fluendo/plugin/TextOverlay.java100644 0 0 5411 11274615664 17744 0ustar 0 0 /* Copyright (C) <2008> ogg.k.ogg.k * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.plugin; import java.awt.*; import java.awt.image.*; /** * This class displays a simple text string on top of incoming video. */ public class TextOverlay extends Overlay { private int font_size = -1; private Font font = null; private String text = null; public TextOverlay() { super(); } /** * Display a text string (from a property) onto the image. */ protected void overlay(com.fluendo.jst.Buffer buf) { Image img; /* img retrieval from VideoSink.java */ if (buf.object instanceof ImageProducer) { img = component.createImage((ImageProducer)buf.object); } else if (buf.object instanceof Image) { img = (Image)buf.object; } else { System.out.println(this+": unknown buffer received "+buf); return; } Dimension d = component.getSize(); int x = 0; int y = 0; int w = d.width; int h = d.height; int new_font_size = w / 32; if (new_font_size < 12) new_font_size = 12; if (font == null || new_font_size != font_size) { font_size = new_font_size; font = new Font("sans", Font.BOLD, font_size); // TODO: should be selectable ? } Graphics g = img.getGraphics(); g.drawImage(img, x, y, w, h, null); /* render text on top */ if (text != null) { double tw; g.setFont(font); g.setColor(Color.white); FontMetrics fm = g.getFontMetrics(); tw = fm.stringWidth(text); g.drawString(text, x+(int)((w-tw)/2), y+(int)(h*0.85)); } g.dispose(); } public boolean setProperty (String name, java.lang.Object value) { if (name.equals("text")) { text = value.toString(); } else { return super.setProperty(name, value); } return true; } public java.lang.Object getProperty (String name) { if (name.equals("text")) { return text; } else { return super.getProperty(name); } } public String getFactoryName () { return "textoverlay"; } } cortado-0.6.0/src/com/fluendo/plugin/TheoraDec.java100644 0 0 21167 11350725171 17330 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.plugin; import java.util.*; import com.jcraft.jogg.*; import com.fluendo.jheora.*; import com.fluendo.jst.*; import com.fluendo.utils.*; public class TheoraDec extends Element implements OggPayload { private static final byte[] signature = { -128, 0x74, 0x68, 0x65, 0x6f, 0x72, 0x61 }; private Info ti; private Comment tc; private State ts; private Packet op; private int packet; private YUVBuffer yuv; private java.lang.Object last_yuv_obj; private long lastTs; private long lastnondupe = -1; private boolean needKeyframe; private boolean haveBOS = false; private boolean haveDecoder = false; /* * OggPayload interface */ public boolean isType (Packet op) { return typeFind (op.packet_base, op.packet, op.bytes) > 0; } public int takeHeader (Packet op) { int ret; byte header; ret = ti.decodeHeader(tc, op); header = op.packet_base[op.packet]; if (header == -128) { haveBOS = true; } else if (header == -126) { ts.decodeInit(ti); haveDecoder = true; } return ret; } public boolean isHeader (Packet op) { return (op.packet_base[op.packet] & 0x80) == 0x80; } public boolean isKeyFrame (Packet op) { return ts.isKeyframe(op); } public boolean isDiscontinuous () { return false; } public long getFirstTs (Vector packets) { int len = packets.size(); int i; long time; com.fluendo.jst.Buffer data = null; /* first find buffer with valid offset */ for (i=0; i>ti.keyframe_granule_shift; long pframe=gp-(iframe< 0) { if ((op.packet_base[op.packet] & 0x80) == 0x80) { Debug.log(Debug.INFO, "ignoring header"); return OK; } if (needKeyframe && ts.isKeyframe(op)) { needKeyframe = false; } } else { Debug.log(Debug.DEBUG, "duplicate frame"); } if (!needKeyframe) { try{ if (ts.decodePacketin(op) != 0) { Debug.log(Debug.ERROR, "Bad Theora packet. Most likely not fatal, hoping for better luck next packet."); } if (op.bytes > 0 ) { if (ts.decodeYUVout(yuv) != 0) { buf.free(); postMessage (Message.newError (this, "Error getting the Theora picture")); Debug.log(Debug.ERROR, "Error getting the picture."); return ERROR; } buf.duplicate = false; lastnondupe = timestamp; last_yuv_obj = yuv.getObject(ti.offset_x, ti.offset_y, ti.frame_width, ti.frame_height); } else { if (timestamp-lastnondupe>=Clock.SECOND) { buf.duplicate = false; lastnondupe = timestamp; } else buf.duplicate = true; } buf.object = last_yuv_obj; buf.caps = caps; buf.timestamp = timestamp; Debug.log( Debug.DEBUG, parent.getName() + " >>> " + buf ); result = srcPad.push(buf); } catch (Exception e) { e.printStackTrace(); postMessage (Message.newError (this, e.getMessage())); result = ERROR; } } else { result = OK; buf.free(); } } packet++; return result; } protected boolean activateFunc (int mode) { return true; } }; public TheoraDec() { super(); ti = new Info(); tc = new Comment(); ts = new State(); yuv = new YUVBuffer(); op = new Packet(); addPad (srcPad); addPad (sinkPad); } protected int changeState (int transition) { int res; switch (transition) { case STOP_PAUSE: lastTs = -1; packet = 0; needKeyframe = true; break; default: break; } res = super.changeState (transition); switch (transition) { case PAUSE_STOP: ti.clear(); tc.clear(); ts.clear(); break; default: break; } return res; } public String getFactoryName () { return "theoradec"; } public String getMime () { return "video/x-theora"; } public String getMime (Packet op) { if (!isType(op)) return null; return "video/x-theora"; } public int typeFind (byte[] data, int offset, int length) { if (MemUtils.startsWith (data, offset, length, signature)) return 10; return -1; } } cortado-0.6.0/src/com/fluendo/plugin/VideoSink.java100644 0 0 13632 11350725171 17363 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.plugin; import java.awt.*; import java.awt.image.*; import com.fluendo.utils.*; import com.fluendo.jst.*; public class VideoSink extends Sink { private Component component; private boolean keepAspect; private boolean ignoreAspect; private boolean scale; private Frame frame; private int width, height; private int aspectX, aspectY; private Rectangle bounds; public VideoSink () { keepAspect = true; scale = true; bounds = null; } protected boolean setCapsFunc (Caps caps) { String mime = caps.getMime(); if (!mime.equals ("video/raw")) return false; width = caps.getFieldInt("width", -1); height = caps.getFieldInt("height", -1); if (width == -1 || height == -1) return false; aspectX = caps.getFieldInt("aspect_x", 1); aspectY = caps.getFieldInt("aspect_y", 1); if(!ignoreAspect) { Debug.log(Debug.DEBUG, this+" dimension: "+width+"x"+height+", aspect: "+aspectX+"/"+aspectY); if (aspectY > aspectX) { height = height * aspectY / aspectX; } else { width = width * aspectX / aspectY; } Debug.log(Debug.DEBUG, this+" scaled source: "+width+"x"+height); } component.setVisible(true); return true; } protected int preroll (Buffer buf) { return render (buf); } protected int render (Buffer buf) { Image image; int x, y, w, h; if (!buf.duplicate) { Debug.log( Debug.DEBUG, this.getName() + " starting buffer " + buf ); if (buf.object instanceof ImageProducer) { image = component.createImage((ImageProducer)buf.object); } else if (buf.object instanceof Image) { image = (Image)buf.object; } else { System.out.println(this+": unknown buffer received "+buf); return Pad.ERROR; } if (!component.isVisible()) return Pad.NOT_NEGOTIATED; Graphics graphics = component.getGraphics(); if (keepAspect) { double src_ratio, dst_ratio; if (bounds == null) { bounds = new Rectangle(component.getSize()); } src_ratio = (double) width / height; dst_ratio = (double) bounds.width / bounds.height; if (src_ratio > dst_ratio) { w = bounds.width; h = (int) (bounds.width / src_ratio); x = bounds.x; y = bounds.y + (bounds.height - h) / 2; } else if (src_ratio < dst_ratio) { w = (int) (bounds.height * src_ratio); h = bounds.height; x = bounds.x + (bounds.width - w) / 2; y = bounds.y; } else { x = bounds.x; y = bounds.y; w = bounds.width; h = bounds.height; } } else if (!scale) { w = Math.min (width, bounds.width); h = Math.min (height, bounds.height); x = bounds.x + (bounds.width - w) / 2; y = bounds.y + (bounds.height - h) / 2; } else { /* draw in available area */ w = bounds.width; h = bounds.height; x = 0; y = 0; } graphics.drawImage (image, x, y, w, h, null); Debug.log( Debug.DEBUG, this.getName() + " done with buffer " + buf ); } return Pad.OK; }; public String getFactoryName () { return "videosink"; } /* * component: A java.awt.Component where the video frames will be sent * keep-aspect: String, if "true", the aspect ratio of the input video will be maintained * scale: String, if "true", and keep-aspect is not true, the video * will be scaled to fit the bounding rectangle * * bounds: A java.awt.Rectangle giving the output bounding rectangle. * This must always be set after component, because setting * component resets the bounding rectangle to the full extent * of the component. */ public boolean setProperty (String name, java.lang.Object value) { if (name.equals("component")) { component = (Component) value; } else if (name.equals("keep-aspect")) { keepAspect = String.valueOf(value).equals("true"); } else if(name.equals("ignore-aspect")) { ignoreAspect = value.toString().equals("true"); } else if (name.equals("scale")) { scale = String.valueOf(value).equals("true"); } else if (name.equals("bounds")) { bounds = (Rectangle) value; Debug.info("Video bounding rectangle: x=" + bounds.x + ", y=" + bounds.y + ", w=" + bounds.width + ", h=" + bounds.height ); } else { return super.setProperty(name, value); } return true; } public java.lang.Object getProperty (String name) { if (name.equals("component")) { return component; } else if (name.equals("keep-aspect")) { return (keepAspect ? "true": "false"); } else if (name.equals("bounds")) { return bounds; } else { return super.getProperty(name); } } protected int changeState (int transition) { if (currentState == STOP && pendingState == PAUSE && component == null) { frame = new Frame(); component = (Component) frame; } return super.changeState(transition); } } cortado-0.6.0/src/com/fluendo/plugin/VorbisDec.java100644 0 0 16733 11350725171 17355 0ustar 0 0 /* Copyright (C) <2004> Wim Taymans * * 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; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.fluendo.plugin; import java.util.*; import com.jcraft.jogg.*; import com.jcraft.jorbis.*; import com.fluendo.jst.*; import com.fluendo.utils.*; public class VorbisDec extends Element implements OggPayload { private long packet; private long offset; private Info vi; private Comment vc; private DspState vd; private Block vb; private boolean discont; private Packet op; private float[][][] _pcmf = new float[1][][]; private int[] _index; private static final byte[] signature = { 0x01, 0x76, 0x6f, 0x72, 0x62, 0x69, 0x73 }; public boolean isType (Packet op) { return typeFind (op.packet_base, op.packet, op.bytes) > 0; } public int takeHeader (Packet op) { return vi.synthesis_headerin(vc, op); } public boolean isHeader (Packet op) { return (op.packet_base[op.packet] & 0x01) == 0x01; } public boolean isKeyFrame (Packet op) { return true; } public boolean isDiscontinuous () { return false; } public long getFirstTs (Vector packets) { int len = packets.size(); int i; long total = 0; long prevSamples = 0; Packet p = new Packet(); com.fluendo.jst.Buffer buf; /* add samples */ for (i=0; i 0) { float[][] pcmf=_pcmf[0]; int numbytes = samples * 2 * vi.channels; int k = 0; buf.ensureSize(numbytes); buf.offset = 0; buf.timestamp = timestamp; buf.time_offset = offset; buf.length = numbytes; buf.caps = caps; buf.setFlag (com.fluendo.jst.Buffer.FLAG_DISCONT, discont); discont = false; //System.out.println(vi.rate + " " +target+ " " +samples); for (int j=0; j 32767) val = 32767; else if (val < -32768) val = -32768; buf.data[k] = (byte) ((val >> 8) & 0xff); buf.data[k+1] = (byte) (val & 0xff); k+=2; } } //System.out.println ("decoded "+samples+" samples"); vd.synthesis_read(samples); offset += samples; if ((result = srcPad.push(buf)) != OK) break; } } packet++; return result; } }; public VorbisDec() { super(); vi = new Info(); vc = new Comment(); vd = new DspState(); vb = new Block(vd); op = new Packet(); addPad (srcPad); addPad (sinkPad); } protected int changeState (int transition) { int res; switch (transition) { case STOP_PAUSE: packet = 0; offset = -1; vi.init(); vc.init(); break; default: break; } res = super.changeState (transition); return res; } public String getFactoryName () { return "vorbisdec"; } public String getMime () { return "audio/x-vorbis"; } public String getMime (Packet op) { if (!isType(op)) return null; return getMime(); } public int typeFind (byte[] data, int offset, int length) { if (MemUtils.startsWith (data, offset, length, signature)) return 10; return -1; } } cortado-0.6.0/src/com/fluendo/utils/Base64Converter.java100644 0 0 5306 11270111317 20215 0ustar 0 0 /* Cortado - a video player java applet * Copyright (C) 2004 Fluendo S.L. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. */ package com.fluendo.utils; public class Base64Converter { public static final char[] alphabet = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0 to 7 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 8 to 15 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 16 to 23 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', // 24 to 31 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 32 to 39 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', // 40 to 47 'w', 'x', 'y', 'z', '0', '1', '2', '3', // 48 to 55 '4', '5', '6', '7', '8', '9', '+', '/' }; // 56 to 63 public static String encode (byte[]octetString) { int bits24; int bits6; char[] out = new char[((octetString.length - 1) / 3 + 1) * 4]; int outIndex = 0; int i = 0; while ((i + 3) <= octetString.length) { // store the octets bits24 = (octetString[i++] & 0xFF) << 16; bits24 |= (octetString[i++] & 0xFF) << 8; bits24 |= (octetString[i++] & 0xFF) << 0; bits6 = (bits24 & 0x00FC0000) >> 18; out[outIndex++] = alphabet[bits6]; bits6 = (bits24 & 0x0003F000) >> 12; out[outIndex++] = alphabet[bits6]; bits6 = (bits24 & 0x00000FC0) >> 6; out[outIndex++] = alphabet[bits6]; bits6 = (bits24 & 0x0000003F); out[outIndex++] = alphabet[bits6]; } if (octetString.length - i == 2) { bits24 = (octetString[i] & 0xFF) << 16; bits24 |= (octetString[i + 1] & 0xFF) << 8; bits6 = (bits24 & 0x00FC0000) >> 18; out[outIndex++] = alphabet[bits6]; bits6 = (bits24 & 0x0003F000) >> 12; out[outIndex++] = alphabet[bits6]; bits6 = (bits24 & 0x00000FC0) >> 6; out[outIndex++] = alphabet[bits6]; out[outIndex++] = '='; } else if (octetString.length - i == 1) { bits24 = (octetString[i] & 0xFF) << 16; bits6 = (bits24 & 0x00FC0000) >> 18; out[outIndex++] = alphabet[bits6]; bits6 = (bits24 & 0x0003F000) >> 12; out[outIndex++] = alphabet[bits6]; out[outIndex++] = '='; out[outIndex++] = '='; } return new String (out); } } cortado-0.6.0/src/com/fluendo/utils/Debug.java100644 0 0 4711 11270111317 16326 0ustar 0 0 /* Cortado - a video player java applet * Copyright (C) 2004 Fluendo S.L. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. */ package com.fluendo.utils; public class Debug { public static final int NONE = 0; public static final int ERROR = 1; public static final int WARNING = 2; public static final int INFO = 3; public static final int DEBUG = 4; public static int level = INFO; /* static id counter */ private static int counter = 0; private static long startTime = 0; public static final int genId() { synchronized (Debug.class) { return counter++; } } public static final String[] prefix = { "NONE", "ERRO", "WARN", "INFO", "DBUG"}; public static String rpad(String s, int length) { if ( length > s.length() ) { int sz = length - s.length(); char arr[] = new char[sz]; for (int n=0; n= DEBUG) { System.out.println( "[" + Debug.rpad( Thread.currentThread().getName(), 30 ) + " " + Debug.rpad( Long.toString( t ), 6 ) + " " + prefix[lev] + "] " + line ); } else { System.out.println( "[" + prefix[lev] + "] " + line ); } } } public static void error(String line) { Debug.log( ERROR, line ); } public static void warning(String line) { Debug.log( WARNING, line ); } public static void warn(String line) { Debug.log( WARNING, line ); } public static void info(String line) { Debug.log( INFO, line ); } public static void debug(String line) { Debug.log( DEBUG, line ); } } cortado-0.6.0/src/com/fluendo/utils/MemUtils.java100644 0 0 5620 11270111317 17037 0ustar 0 0 /* Cortado - a video player java applet * Copyright (C) 2004 Fluendo S.L. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. */ package com.fluendo.utils; public class MemUtils { private static final char[] bytes = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' }; public static final int cmp (byte[] mem1, byte[] mem2, int len) { for (int i=0; i 0x20 && b < 0x7f) chars.append (vis.charAt(i)); else chars.append ("."); string.append (bytes[b/16]); string.append (bytes[b%16]); string.append (" "); j++; i++; if (j == 16 || i == len) { System.out.println ("" + (i-j) + " "+ string.toString() + chars.toString()); string.setLength(0); chars.setLength(0); j = 0; } } } } cortado-0.6.0/src/com/jcraft/jogg/Buffer.java100644 0 0 32301 11270111317 16130 0ustar 0 0 /* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jogg; public class Buffer{ private static final int BUFFER_INCREMENT=256; private static final int[] mask={ 0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f, 0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff, 0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff, 0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff, 0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff, 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff, 0x3fffffff,0x7fffffff,0xffffffff }; int ptr=0; byte[] buffer=null; int endbit=0; int endbyte=0; int storage=0; public void writeinit(){ buffer=new byte[BUFFER_INCREMENT]; ptr=0; buffer[0]=(byte)'\0'; storage=BUFFER_INCREMENT; } public void write(byte[] s){ for(int i=0; iret="+Integer.toHexString(ret)); if(bits>32 && endbit!=0){ ret|=((buffer[ptr+4])&0xff)<<(32-endbit); // ret|=((byte)(buffer[ptr+4]))<<(32-endbit); } } } } return(m&ret); } public int look1(){ if(endbyte>=storage)return(-1); return((buffer[ptr]>>endbit)&1); } public void adv(int bits){ bits+=endbit; ptr+=bits/8; endbyte+=bits/8; endbit=bits&7; } public void adv1(){ ++endbit; if(endbit>7){ endbit=0; ptr++; endbyte++; } } public int read(int bits){ //System.err.println(this+" read: bits="+bits+", storage="+storage+", endbyte="+endbyte+ // ", ptr="+ptr+", endbit="+endbit+", buf[ptr]="+buffer[ptr]); int ret; int m=mask[bits]; bits+=endbit; if(endbyte+4>=storage){ ret=-1; if(endbyte+(bits-1)/8>=storage){ ptr+=bits/8; endbyte+=bits/8; endbit=bits&7; return(ret); } } ret=((buffer[ptr])&0xff)>>>endbit; if(bits>8){ ret|=((buffer[ptr+1])&0xff)<<(8-endbit); if(bits>16){ ret|=((buffer[ptr+2])&0xff)<<(16-endbit); if(bits>24){ ret|=((buffer[ptr+3])&0xff)<<(24-endbit); if(bits>32 && endbit!=0){ ret|=((buffer[ptr+4])&0xff)<<(32-endbit); } } } } ret&=m; ptr+=bits/8; endbyte+=bits/8; endbit=bits&7; return(ret); } public int readB(int bits){ //System.err.println(this+" read: bits="+bits+", storage="+storage+", endbyte="+endbyte+ // ", ptr="+ptr+", endbit="+endbit+", buf[ptr]="+buffer[ptr]); int ret; int m=32-bits; bits+=endbit; if(endbyte+4>=storage){ /* not the main path */ ret=-1; if(endbyte*8+bits>storage*8) { ptr+=bits/8; endbyte+=bits/8; endbit=bits&7; return(ret); } } ret=(buffer[ptr]&0xff)<<(24+endbit); if(bits>8){ ret|=(buffer[ptr+1]&0xff)<<(16+endbit); if(bits>16){ ret|=(buffer[ptr+2]&0xff)<<(8+endbit); if(bits>24){ ret|=(buffer[ptr+3]&0xff)<<(endbit); if(bits>32 && (endbit != 0)) ret|=(buffer[ptr+4]&0xff)>>(8-endbit); } } } ret=(ret>>>(m>>1))>>>((m+1)>>1); ptr+=bits/8; endbyte+=bits/8; endbit=bits&7; return(ret); } public int read1(){ int ret; if(endbyte>=storage){ ret=-1; endbit++; if(endbit>7){ endbit=0; ptr++; endbyte++; } return(ret); } ret=(buffer[ptr]>>endbit)&1; endbit++; if(endbit>7){ endbit=0; ptr++; endbyte++; } return(ret); } public int bytes(){ return(endbyte+(endbit+7)/8); } public int bits(){ return(endbyte*8+endbit); } public byte[] buffer(){ return(buffer); } public static int ilog(int v){ int ret=0; while(v>0){ ret++; v>>>=1; } return(ret); } public static void report(String in){ System.err.println(in); System.exit(1); } /* static void cliptest(int[] b, int vals, int bits, int[] comp, int compsize){ int bytes; byte[] buffer; o.reset(); for(int i=0;i * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jogg; public class Packet{ public byte[] packet_base; public int packet; public int bytes; public int b_o_s; public int e_o_s; public long granulepos; public long packetno; // sequence number for decode; the framing // knows where there's a hole in the data, // but we need coupling so that the codec // (which is in a seperate abstraction // layer) also knows about the gap /* // TEST static int sequence=0; static int lastno=0; void checkpacket(int len, int no, int pos){ if(bytes!=len){ System.err.println("incorrect packet length!"); System.exit(1); } if(granulepos!=pos){ System.err.println("incorrect packet position!"); System.exit(1); } // packet number just follows sequence/gap; adjust the input number // for that if(no==0){ sequence=0; } else{ sequence++; if(no>lastno+1) sequence++; } lastno=no; if(packetno!=sequence){ System.err.println("incorrect packet sequence "+packetno+" != "+sequence); System.exit(1); } // Test data for(int j=0;j * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jogg; public class Page{ private static int[] crc_lookup=new int[256]; static { for(int i=0; i>>24)&0xff)^(header_base[header+i]&0xff)]; } for(int i=0;i>>24)&0xff)^(body_base[body+i]&0xff)]; } header_base[header+22]=(byte)crc_reg/*&0xff*/; header_base[header+23]=(byte)(crc_reg>>>8)/*&0xff*/; header_base[header+24]=(byte)(crc_reg>>>16)/*&0xff*/; header_base[header+25]=(byte)(crc_reg>>>24)/*&0xff*/; } /* // TEST static StreamState os_en, os_de; static SyncState oy; void check_page(byte[] data_base, int data, int[] _header){ // Test data for(int j=0;j 4k... "); test_pack(packets,headret); } { // continuing packet test int[] packets={0,4345,259,255,-1}; int[] head1={0x4f,0x67,0x67,0x53,0,0x02, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x02,0x03,0x04,0,0,0,0, 0xff,0x7b,0x23,0x17, 1, 0}; int[] head2={0x4f,0x67,0x67,0x53,0,0x00, 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x02,0x03,0x04,1,0,0,0, 0x34,0x24,0xd5,0x29, 17, 255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255}; int[] head3={0x4f,0x67,0x67,0x53,0,0x05, 0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x02,0x03,0x04,2,0,0,0, 0xc8,0xc3,0xcb,0xed, 5, 10,255,4,255,0}; int[][] headret={head1,head2,head3,null}; System.err.print("testing single packet page span... "); test_pack(packets,headret); } // page with the 255 segment limit { int[] packets={0,10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,50,-1}; int[] head1={0x4f,0x67,0x67,0x53,0,0x02, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x02,0x03,0x04,0,0,0,0, 0xff,0x7b,0x23,0x17, 1, 0}; int[] head2={0x4f,0x67,0x67,0x53,0,0x00, 0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00, 0x01,0x02,0x03,0x04,1,0,0,0, 0xed,0x2a,0x2e,0xa7, 255, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10}; int[] head3={0x4f,0x67,0x67,0x53,0,0x04, 0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00, 0x01,0x02,0x03,0x04,2,0,0,0, 0x6c,0x3b,0x82,0x3d, 1, 50}; int[][] headret={head1,head2,head3,null}; System.err.print("testing max packet segments... "); test_pack(packets,headret); } { // packet that overspans over an entire page int[] packets={0,100,9000,259,255,-1}; int[] head1={0x4f,0x67,0x67,0x53,0,0x02, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x02,0x03,0x04,0,0,0,0, 0xff,0x7b,0x23,0x17, 1, 0}; int[] head2={0x4f,0x67,0x67,0x53,0,0x00, 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x02,0x03,0x04,1,0,0,0, 0x3c,0xd9,0x4d,0x3f, 17, 100,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255}; int[] head3={0x4f,0x67,0x67,0x53,0,0x01, 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x02,0x03,0x04,2,0,0,0, 0xbd,0xd5,0xb5,0x8b, 17, 255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255}; int[] head4={0x4f,0x67,0x67,0x53,0,0x05, 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x02,0x03,0x04,3,0,0,0, 0xef,0xdd,0x88,0xde, 7, 255,255,75,255,4,255,0}; int[][] headret={head1,head2,head3,head4,null}; System.err.print("testing very large packets... "); test_pack(packets,headret); } { // term only page. why not? int[] packets={0,100,4080,-1}; int[] head1={0x4f,0x67,0x67,0x53,0,0x02, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x02,0x03,0x04,0,0,0,0, 0xff,0x7b,0x23,0x17, 1, 0}; int[] head2={0x4f,0x67,0x67,0x53,0,0x00, 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x02,0x03,0x04,1,0,0,0, 0x3c,0xd9,0x4d,0x3f, 17, 100,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255}; int[] head3={0x4f,0x67,0x67,0x53,0,0x05, 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x02,0x03,0x04,2,0,0,0, 0xd4,0xe0,0x60,0xe5, 1,0}; int[][] headret={head1,head2,head3,null}; System.err.print("testing zero data page (1 nil packet)... "); test_pack(packets,headret); } { // build a bunch of pages for testing byte[] data=new byte[1024*1024]; int[] pl={0,100,4079,2956,2057,76,34,912,0,234,1000,1000,1000,300,-1}; int inptr=0; Page[] og=new Page[5]; for(int i=0; i<5; i++){ og[i]=new Page(); } os_en.reset(); for(int i=0;pl[i]!=-1;i++){ Packet op=new Packet(); int len=pl[i]; op.packet_base=data; op.packet=inptr; op.bytes=len; op.e_o_s=(pl[i+1]<0?1:0); op.granulepos=(i+1)*1000; for(int j=0;j0)error(); // Test fractional page inputs: incomplete fixed header index=oy.buffer(og[1].header_len); System.arraycopy(og[1].header_base, og[1].header+3, oy.data, index, 20); oy.wrote(20); if(oy.pageout(og_de)>0)error(); // Test fractional page inputs: incomplete header index=oy.buffer(og[1].header_len); System.arraycopy(og[1].header_base, og[1].header+23, oy.data, index, 5); oy.wrote(5); if(oy.pageout(og_de)>0)error(); // Test fractional page inputs: incomplete body index=oy.buffer(og[1].header_len); System.arraycopy(og[1].header_base, og[1].header+28, oy.data, index, og[1].header_len-28); oy.wrote(og[1].header_len-28); if(oy.pageout(og_de)>0)error(); index=oy.buffer(og[1].body_len); System.arraycopy(og[1].body_base, og[1].body, oy.data, index, 1000); oy.wrote(1000); if(oy.pageout(og_de)>0)error(); index=oy.buffer(og[1].body_len); System.arraycopy(og[1].body_base, og[1].body+1000, oy.data, index, og[1].body_len-1000); oy.wrote(og[1].body_len-1000); if(oy.pageout(og_de)<=0)error(); System.err.println("ok."); } // Test fractional page inputs: page + incomplete capture { Page og_de=new Page(); System.err.print("Testing sync on 1+partial inputs... "); oy.reset(); int index=oy.buffer(og[1].header_len); System.arraycopy(og[1].header_base, og[1].header, oy.data, index, og[1].header_len); oy.wrote(og[1].header_len); index=oy.buffer(og[1].body_len); System.arraycopy(og[1].body_base, og[1].body, oy.data, index, og[1].body_len); oy.wrote(og[1].body_len); index=oy.buffer(og[1].header_len); System.arraycopy(og[1].header_base, og[1].header, oy.data, index, 20); oy.wrote(20); if(oy.pageout(og_de)<=0)error(); if(oy.pageout(og_de)>0)error(); index=oy.buffer(og[1].header_len); System.arraycopy(og[1].header_base, og[1].header+20, oy.data, index, og[1].header_len-20); oy.wrote(og[1].header_len-20); index=oy.buffer(og[1].body_len); System.arraycopy(og[1].body_base, og[1].body, oy.data, index, og[1].body_len); oy.wrote(og[1].body_len); if(oy.pageout(og_de)<=0)error(); System.err.println("ok."); } // // // // // // // // // // Test recapture: garbage + page { Page og_de=new Page(); System.err.print("Testing search for capture... "); oy.reset(); // 'garbage' int index=oy.buffer(og[1].body_len); System.arraycopy(og[1].body_base, og[1].body, oy.data, index, og[1].body_len); oy.wrote(og[1].body_len); index=oy.buffer(og[1].header_len); System.arraycopy(og[1].header_base, og[1].header, oy.data, index, og[1].header_len); oy.wrote(og[1].header_len); index=oy.buffer(og[1].body_len); System.arraycopy(og[1].body_base, og[1].body, oy.data, index, og[1].body_len); oy.wrote(og[1].body_len); index=oy.buffer(og[2].header_len); System.arraycopy(og[2].header_base, og[2].header, oy.data, index, 20); oy.wrote(20); if(oy.pageout(og_de)>0)error(); if(oy.pageout(og_de)<=0)error(); if(oy.pageout(og_de)>0)error(); index=oy.buffer(og[2].header_len); System.arraycopy(og[2].header_base, og[2].header+20, oy.data, index, og[2].header_len-20); oy.wrote(og[2].header_len-20); index=oy.buffer(og[2].body_len); System.arraycopy(og[2].body_base, og[2].body, oy.data, index, og[2].body_len); oy.wrote(og[2].body_len); if(oy.pageout(og_de)<=0)error(); System.err.println("ok."); } // Test recapture: page + garbage + page { Page og_de=new Page(); System.err.print("Testing recapture... "); oy.reset(); int index=oy.buffer(og[1].header_len); System.arraycopy(og[1].header_base, og[1].header, oy.data, index, og[1].header_len); oy.wrote(og[1].header_len); index=oy.buffer(og[1].body_len); System.arraycopy(og[1].body_base, og[1].body, oy.data, index, og[1].body_len); oy.wrote(og[1].body_len); index=oy.buffer(og[2].header_len); System.arraycopy(og[2].header_base, og[2].header, oy.data, index, og[2].header_len); oy.wrote(og[2].header_len); index=oy.buffer(og[2].header_len); System.arraycopy(og[2].header_base, og[2].header, oy.data, index, og[2].header_len); oy.wrote(og[2].header_len); if(oy.pageout(og_de)<=0)error(); index=oy.buffer(og[2].body_len); System.arraycopy(og[2].body_base, og[2].body, oy.data, index, og[2].body_len-5); oy.wrote(og[2].body_len-5); index=oy.buffer(og[3].header_len); System.arraycopy(og[3].header_base, og[3].header, oy.data, index, og[3].header_len); oy.wrote(og[3].header_len); index=oy.buffer(og[3].body_len); System.arraycopy(og[3].body_base, og[3].body, oy.data, index, og[3].body_len); oy.wrote(og[3].body_len); if(oy.pageout(og_de)>0)error(); if(oy.pageout(og_de)<=0)error(); System.err.println("ok."); } } //return(0); } */ } cortado-0.6.0/src/com/jcraft/jogg/StreamState.java100644 0 0 44015 11272111150 17155 0ustar 0 0 /* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jogg; public class StreamState{ byte[] body_data; /* bytes from packet bodies */ int body_storage; /* storage elements allocated */ int body_fill; /* elements stored; fill mark */ private int body_returned; /* elements of fill returned */ int[] lacing_vals; /* The values that will go to the segment table */ long[] granule_vals; /* pcm_pos values for headers. Not compact this way, but it is simple coupled to the lacing fifo */ int lacing_storage; int lacing_fill; int lacing_packet; int lacing_returned; byte[] header=new byte[282]; /* working space for header encode */ int header_fill; public int e_o_s; /* set when we have buffered the last packet in the logical bitstream */ int b_o_s; /* set after we've written the initial page of a logical bitstream */ int serialno; int pageno; long packetno; /* sequence number for decode; the framing knows where there's a hole in the data, but we need coupling so that the codec (which is in a seperate abstraction layer) also knows about the gap */ long granulepos; public StreamState(){ init(); } StreamState(int serialno){ this(); init(serialno); } void init(){ body_storage=16*1024; body_data=new byte[body_storage]; lacing_storage=1024; lacing_vals=new int[lacing_storage]; granule_vals=new long[lacing_storage]; } public void init(int serialno){ if(body_data==null){ init(); } else{ for(int i=0; i255?255:lacing_fill); int bytes=0; int acc=0; long granule_pos=granule_vals[0]; if(maxvals==0)return(0); /* construct a page */ /* decide how many segments to include */ /* If this is the initial header case, the first page must only include the initial header packet */ if(b_o_s==0){ /* 'initial header page' case */ granule_pos=0; for(vals=0;vals4096)break; acc+=(lacing_vals[vals]&0x0ff); granule_pos=granule_vals[vals]; } } /* construct the header in temp storage */ System.arraycopy("OggS".getBytes(), 0, header, 0, 4); /* stream structure version */ header[4]=0x00; /* continued packet flag? */ header[5]=0x00; if((lacing_vals[0]&0x100)==0)header[5]|=0x01; /* first page flag? */ if(b_o_s==0) header[5]|=0x02; /* last page flag? */ if(e_o_s!=0 && lacing_fill==vals) header[5]|=0x04; b_o_s=1; /* 64 bits of PCM position */ for(i=6;i<14;i++){ header[i]=(byte)granule_pos; granule_pos>>>=8; } /* 32 bits of stream serial number */ { int _serialno=serialno; for(i=14;i<18;i++){ header[i]=(byte)_serialno; _serialno>>>=8; } } /* 32 bits of page counter (we have both counter and page header because this val can roll over) */ if(pageno==-1)pageno=0; /* because someone called stream_reset; this would be a strange thing to do in an encode stream, but it has plausible uses */ { int _pageno=pageno++; for(i=18;i<22;i++){ header[i]=(byte)_pageno; _pageno>>>=8; } } /* zero for computation; filled in later */ header[22]=0; header[23]=0; header[24]=0; header[25]=0; /* segment table */ header[26]=(byte)vals; for(i=0;i>>=8; // } // // /* 32 bits of stream serial number */ // { // int serialn=serialno; // for(int i=14;i<18;i++){ // header[i]=(byte)serialn; // serialn>>>=8; // } // } // // ///* 32 bits of page counter (we have both counter and page header // because this val can roll over) */ // if(pageno==-1)pageno=0; /* because someone called // stream_reset; this would be a // strange thing to do in an // encode stream, but it has // plausible uses */ // { // int pagen=pageno++; // for(int i=18;i<22;i++){ // header[i]=(byte)pagen; // pagen>>>=8; // } // } // // /* zero for computation; filled in later */ // header[22]=0; // header[23]=0; // header[24]=0; // header[25]=0; // // /* segment table */ // header[26]=(byte)vals; // for(int i=0;i 4096 || /* 'page nominal size' case */ lacing_fill>=255 || /* 'segment table full' case */ (lacing_fill!=0&&b_o_s==0)){ /* 'initial header page' case */ return flush(og); } return 0; } public int eof(){ return e_o_s; } public int reset(){ body_fill=0; body_returned=0; lacing_fill=0; lacing_packet=0; lacing_returned=0; header_fill=0; e_o_s=0; b_o_s=0; pageno=-1; packetno=0; granulepos=0; return(0); } } cortado-0.6.0/src/com/jcraft/jogg/SyncState.java100644 0 0 16267 11270111317 16651 0ustar 0 0 /* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jogg; // DECODING PRIMITIVES: packet streaming layer // This has two layers to place more of the multi-serialno and paging // control in the application's hands. First, we expose a data buffer // using ogg_decode_buffer(). The app either copies into the // buffer, or passes it directly to read(), etc. We then call // ogg_decode_wrote() to tell how many bytes we just added. // // Pages are returned (pointers into the buffer in ogg_sync_state) // by ogg_decode_stream(). The page is then submitted to // ogg_decode_page() along with the appropriate // ogg_stream_state* (ie, matching serialno). We then get raw // packets out calling ogg_stream_packet() with a // ogg_stream_state. See the 'frame-prog.txt' docs for details and // example code. public class SyncState{ public byte[] data; int storage; int fill; int returned; int unsynced; int headerbytes; int bodybytes; public int clear(){ data=null; return(0); } // !!!!!!!!!!!! // byte[] buffer(int size){ public int buffer(int size){ // first, clear out any space that has been previously returned if(returned!=0){ fill-=returned; if(fill>0){ System.arraycopy(data, returned, data, 0, fill); } returned=0; } if(size>storage-fill){ // We need to extend the internal buffer int newsize=size+fill+4096; // an extra page to be nice if(data!=null){ byte[] foo=new byte[newsize]; System.arraycopy(data, 0, foo, 0, data.length); data=foo; } else{ data=new byte[newsize]; } storage=newsize; } // expose a segment at least as large as requested at the fill mark // return((char *)oy->data+oy->fill); // return(data); return(fill); } public int wrote(int bytes){ if(fill+bytes>storage)return(-1); fill+=bytes; return(0); } // sync the stream. This is meant to be useful for finding page // boundaries. // // return values for this: // -n) skipped n bytes // 0) page not ready; more data (no bytes skipped) // n) page synced at current location; page length n bytes private Page pageseek=new Page(); private byte[] chksum=new byte[4]; public int pageseek(Page og){ int page=returned; int next; int bytes=fill-returned; if(headerbytes==0){ int _headerbytes,i; if(bytes<27)return(0); // not enough for a header /* verify capture pattern */ //!!!!!!!!!!! if(data[page]!='O' || data[page+1]!='g' || data[page+2]!='g' || data[page+3]!='S'){ headerbytes=0; bodybytes=0; // search for possible capture next=0; for(int ii=0; iibytes)return(0); // The whole test page is buffered. Verify the checksum synchronized(chksum){ // Grab the checksum bytes, set the header field to zero System.arraycopy(data, page+22, chksum, 0, 4); data[page+22]=0; data[page+23]=0; data[page+24]=0; data[page+25]=0; // set up a temp page struct and recompute the checksum Page log=pageseek; log.header_base=data; log.header=page; log.header_len=headerbytes; log.body_base=data; log.body=page+headerbytes; log.body_len=bodybytes; log.checksum(); // Compare if(chksum[0]!=data[page+22] || chksum[1]!=data[page+23] || chksum[2]!=data[page+24] || chksum[3]!=data[page+25]){ // D'oh. Mismatch! Corrupt page (or miscapture and not a page at all) // replace the computed checksum with the one actually read in System.arraycopy(chksum, 0, data, page+22, 4); // Bad checksum. Lose sync */ headerbytes=0; bodybytes=0; // search for possible capture next=0; for(int ii=0; ii0){ // have a page return(1); } if(ret==0){ // need more data return(0); } // head did not start a synced page... skipped some bytes if(unsynced==0){ unsynced=1; return(-1); } // loop. keep looking } } // clear things to an initial state. Good to call, eg, before seeking public int reset(){ fill=0; returned=0; unsynced=0; headerbytes=0; bodybytes=0; return(0); } public void init(){} } cortado-0.6.0/src/com/jcraft/jorbis/AllocChain.java100644 0 0 2075 11270111317 17243 0ustar 0 0 /* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; class AllocChain{ Object ptr; AllocChain next; }; cortado-0.6.0/src/com/jcraft/jorbis/Block.java100644 0 0 11103 11270111317 16310 0ustar 0 0 /* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; import com.jcraft.jogg.*; public class Block{ ///necessary stream state for linking to the framing abstraction float[][] pcm=new float[0][]; // this is a pointer into local storage Buffer opb=new Buffer(); int lW; int W; int nW; int pcmend; int mode; int eofflag; long granulepos; long sequence; DspState vd; // For read-only access of configuration // local storage to avoid remallocing; it's up to the mapping to // structure it //byte[] localstore; //int localtop; //int localalloc; //int totaluse; //AllocChain reap; // bitmetrics for the frame int glue_bits; int time_bits; int floor_bits; int res_bits; public Block(DspState vd){ this.vd=vd; // localalloc=0; // localstore=null; if(vd.analysisp!=0){ opb.writeinit(); } } public void init(DspState vd){ this.vd=vd; } // int alloc(int bytes){ // bytes=(bytes+(8-1))&(~(8-1)); // if(bytes+localtop>localalloc){ // if(localstore!=null){ // AllocChain link=new AllocChain(); // totaluse+=localtop; // link.next=reap; // link.ptr=localstore; // reap=link; // } // // highly conservative // localalloc=bytes; // localstore=new byte[localalloc]; // localtop=0; // } // { // int foo=localtop; // //void *ret=(void *)(((char *)vb->localstore)+vb->localtop); // localtop+=bytes; // return foo; // } // } // reap the chain, pull the ripcord // void ripcord(){ // // reap the chain // while(reap!=null){ // AllocChain next=reap.next; // //free(reap->ptr); // reap.ptr=null; // //memset(reap,0,sizeof(struct alloc_chain)); // //free(reap); // reap=next; // } // // consolidate storage // if(totaluse!=0){ // //vb->localstore=realloc(vb->localstore,vb->totaluse+vb->localalloc); // byte[] foo=new byte[totaluse+localalloc]; // System.arraycopy(localstore, 0, foo, 0, localstore.length); // localstore=foo; // localalloc+=totaluse; // totaluse=0; // } // // pull the ripcord // localtop=0; // reap=null; // } public int clear(){ if(vd!=null){ if(vd.analysisp!=0){ opb.writeclear(); } } //ripcord(); //if(localstore!=null) // localstore=null; //memset(vb,0,sizeof(vorbis_block)); return(0); } public int synthesis(Packet op){ Info vi=vd.vi; // first things first. Make sure decode is ready // ripcord(); opb.readinit(op.packet_base, op.packet, op.bytes); // Check the packet type if(opb.read(1)!=0){ // Oops. This is not an audio data packet return(-1); } // read our mode and pre/post windowsize int _mode=opb.read(vd.modebits); if(_mode==-1)return(-1); mode=_mode; W=vi.mode_param[mode].blockflag; if(W!=0){ lW=opb.read(1); nW=opb.read(1); if(nW==-1) return(-1); } else{ lW=0; nW=0; } // more setup granulepos=op.granulepos; sequence=op.packetno-3; // first block is third packet eofflag=op.e_o_s; // alloc pcm passback storage pcmend=vi.blocksizes[W]; //pcm=alloc(vi.channels); if(pcm.length * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; class ChainingExample{ public static void main(String[] arg){ VorbisFile ov=null; try{ ov=new VorbisFile(System.in, null, -1); } catch(Exception e){ System.err.println(e); return; } if(ov.seekable()){ System.out.println("Input bitstream contained "+ov.streams()+" logical bitstream section(s)."); System.out.println("Total bitstream playing time: "+ov.time_total(-1)+" seconds\n"); } else{ System.out.println("Standard input was not seekable."); System.out.println("First logical bitstream information:\n"); } for(int i=0;i * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; import com.jcraft.jogg.*; class CodeBook{ int dim; // codebook dimensions (elements per vector) int entries; // codebook entries StaticCodeBook c=new StaticCodeBook(); float[] valuelist; // list of dim*entries actual entry values int[] codelist; // list of bitstream codewords for each entry DecodeAux decode_tree; // returns the number of bits int encode(int a, Buffer b){ b.write(codelist[a], c.lengthlist[a]); return(c.lengthlist[a]); } // One the encode side, our vector writers are each designed for a // specific purpose, and the encoder is not flexible without modification: // // The LSP vector coder uses a single stage nearest-match with no // interleave, so no step and no error return. This is specced by floor0 // and doesn't change. // // Residue0 encoding interleaves, uses multiple stages, and each stage // peels of a specific amount of resolution from a lattice (thus we want // to match by threshhold, not nearest match). Residue doesn't *have* to // be encoded that way, but to change it, one will need to add more // infrastructure on the encode side (decode side is specced and simpler) // floor0 LSP (single stage, non interleaved, nearest match) // returns entry number and *modifies a* to the quantization value int errorv(float[] a){ int best=best(a,1); for(int k=0;k8){ for(i=0;i.000001){ System.err.print("read ("+iv[i]+") != written ("+qv[i]+") at position ("+i+")\n"); System.exit(1); } } System.err.print("OK\n"); ptr++; } // The above is the trivial stuff; // now try unquantizing a log scale codebook } */ } class DecodeAux{ int[] tab; int[] tabl; int tabn; int[] ptr0; int[] ptr1; int aux; // number of tree entries } cortado-0.6.0/src/com/jcraft/jorbis/Comment.java100644 0 0 14307 11270111317 16671 0ustar 0 0 /* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; import com.jcraft.jogg.*; // the comments are not part of vorbis_info so that vorbis_info can be // static storage public class Comment{ private static byte[] _vorbis="vorbis".getBytes(); private static final int OV_EFAULT=-129; private static final int OV_EIMPL=-130; // unlimited user comment fields. libvorbis writes 'libvorbis' // whatever vendor is set to in encode public byte[][] user_comments; public int[] comment_lengths; public int comments; public byte[] vendor; public void init(){ user_comments=null; comments=0; vendor=null; } public void add(String comment){ add(comment.getBytes()); } private void add(byte[] comment){ byte[][] foo=new byte[comments+2][]; if(user_comments!=null){ System.arraycopy(user_comments, 0, foo, 0, comments); } user_comments=foo; int[] goo=new int[comments+2]; if(comment_lengths!=null){ System.arraycopy(comment_lengths, 0, goo, 0, comments); } comment_lengths=goo; byte[] bar=new byte[comment.length+1]; System.arraycopy(comment, 0, bar, 0, comment.length); user_comments[comments]=bar; comment_lengths[comments]=comment.length; comments++; user_comments[comments]=null; } public void add_tag(String tag, String contents){ if(contents==null) contents=""; add(tag+"="+contents); } /* private void add_tag(byte[] tag, byte[] contents){ byte[] foo=new byte[tag.length+contents.length+1]; int j=0; for(int i=0; i='A')u1=(byte)(u1-'A'+'a'); if(u2>='A')u2=(byte)(u2-'A'+'a'); if(u1!=u2){ return false; } c++; } return true; } public String query(String tag){ return query(tag, 0); } public String query(String tag, int count){ int foo=query(tag.getBytes(), count); if(foo==-1)return null; byte[] comment=user_comments[foo]; for(int i=0; i * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; import com.jcraft.jogg.*; // Takes a vorbis bitstream from stdin and writes raw stereo PCM to // stdout. Decodes simple and chained OggVorbis files from beginning // to end. Vorbisfile.a is somewhat more complex than the code below. class DecodeExample{ static int convsize=4096*2; static byte[] convbuffer=new byte[convsize]; // take 8k out of the data segment, not the stack public static void main(String[] arg){ java.io.InputStream input=System.in; if(arg.length>0){ try{ input=new java.io.FileInputStream(arg[0]); } catch(Exception e){ System.err.println(e); } } SyncState oy=new SyncState(); // sync and verify incoming physical bitstream StreamState os=new StreamState(); // take physical pages, weld into a logical stream of packets Page og=new Page(); // one Ogg bitstream page. Vorbis packets are inside Packet op=new Packet(); // one raw packet of data for decode Info vi=new Info(); // struct that stores all the static vorbis bitstream settings Comment vc=new Comment(); // struct that stores all the bitstream user comments DspState vd=new DspState(); // central working state for the packet->PCM decoder Block vb=new Block(vd); // local working space for packet->PCM decode byte[] buffer; int bytes=0; // Decode setup oy.init(); // Now we can read pages while(true){ // we repeat if the bitstream is chained int eos=0; // grab some data at the head of the stream. We want the first page // (which is guaranteed to be small and only contain the Vorbis // stream initial header) We need the first page to get the stream // serialno. // submit a 4k block to libvorbis' Ogg layer int index=oy.buffer(4096); buffer=oy.data; try{ bytes=input.read(buffer, index, 4096); } catch(Exception e){ System.err.println(e); System.exit(-1); } oy.wrote(bytes); // Get the first page. if(oy.pageout(og)!=1){ // have we simply run out of data? If so, we're done. if(bytes<4096)break; // error case. Must not be Vorbis data System.err.println("Input does not appear to be an Ogg bitstream."); System.exit(1); } // Get the serial number and set up the rest of decode. // serialno first; use it to set up a logical stream os.init(og.serialno()); // extract the initial header from the first page and verify that the // Ogg bitstream is in fact Vorbis data // I handle the initial header first instead of just having the code // read all three Vorbis headers at once because reading the initial // header is an easy way to identify a Vorbis bitstream and it's // useful to see that functionality seperated out. vi.init(); vc.init(); if(os.pagein(og)<0){ // error; stream version mismatch perhaps System.err.println("Error reading first page of Ogg bitstream data."); System.exit(1); } if(os.packetout(op)!=1){ // no page? must not be vorbis System.err.println("Error reading initial header packet."); System.exit(1); } if(vi.synthesis_headerin(vc,op)<0){ // error case; not a vorbis header System.err.println("This Ogg bitstream does not contain Vorbis audio data."); System.exit(1); } // At this point, we're sure we're Vorbis. We've set up the logical // (Ogg) bitstream decoder. Get the comment and codebook headers and // set up the Vorbis decoder // The next two packets in order are the comment and codebook headers. // They're likely large and may span multiple pages. Thus we reead // and submit data until we get our two pacakets, watching that no // pages are missing. If a page is missing, error out; losing a // header page is the only place where missing data is fatal. */ int i=0; while(i<2){ while(i<2){ int result=oy.pageout(og); if(result==0) break; // Need more data // Don't complain about missing or corrupt data yet. We'll // catch it at the packet output phase if(result==1){ os.pagein(og); // we can ignore any errors here // as they'll also become apparent // at packetout while(i<2){ result=os.packetout(op); if(result==0)break; if(result==-1){ // Uh oh; data at some point was corrupted or missing! // We can't tolerate that in a header. Die. System.err.println("Corrupt secondary header. Exiting."); System.exit(1); } vi.synthesis_headerin(vc,op); i++; } } } // no harm in not checking before adding more index=oy.buffer(4096); buffer=oy.data; try{ bytes=input.read(buffer, index, 4096); } catch(Exception e){ System.err.println(e); System.exit(1); } if(bytes==0 && i<2){ System.err.println("End of file before finding all Vorbis headers!"); System.exit(1); } oy.wrote(bytes); } // Throw the comments plus a few lines about the bitstream we're // decoding { byte[][] ptr=vc.user_comments; for(int j=0; jPCM decoder. vd.synthesis_init(vi); // central decode state vb.init(vd); // 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 float[][][] _pcm=new float[1][][]; int[] _index=new int[vi.channels]; // The rest is just a straight decode loop until end of stream while(eos==0){ while(eos==0){ int result=oy.pageout(og); if(result==0)break; // need more data if(result==-1){ // missing or corrupt data at this page position System.err.println("Corrupt or missing data in bitstream; continuing..."); } else{ os.pagein(og); // can safely ignore errors at // this point while(true){ result=os.packetout(op); if(result==0)break; // need more data if(result==-1){ // missing or corrupt data at this page position // no reason to complain; already complained above } else{ // we have a packet. Decode it int samples; if(vb.synthesis(op)==0){ // test for success! vd.synthesis_blockin(vb); } // **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 while((samples=vd.synthesis_pcmout(_pcm, _index))>0){ float[][] pcm=_pcm[0]; boolean clipflag=false; int bout=(samples32767){ val=32767; clipflag=true; } if(val<-32768){ val=-32768; clipflag=true; } if(val<0) val=val|0x8000; convbuffer[ptr]=(byte)(val); convbuffer[ptr+1]=(byte)(val>>>8); ptr+=2*(vi.channels); } } //if(clipflag) // System.err.println("Clipping in frame "+vd.sequence); System.out.write(convbuffer, 0, 2*vi.channels*bout); vd.synthesis_read(bout); // tell libvorbis how // many samples we // actually consumed } } } if(og.eos()!=0)eos=1; } } if(eos==0){ index=oy.buffer(4096); buffer=oy.data; try{ bytes=input.read(buffer,index,4096); } catch(Exception e){ System.err.println(e); System.exit(1); } oy.wrote(bytes); if(bytes==0)eos=1; } } // clean up this logical bitstream; before exit we see if we're // followed by another [chained] os.clear(); // ogg_page and ogg_packet structs always point to storage in // libvorbis. They're never freed or manipulated directly vb.clear(); vd.clear(); vi.clear(); // must be called last } // OK, clean up the framer oy.clear(); System.err.println("Done."); } } cortado-0.6.0/src/com/jcraft/jorbis/Drft.java100644 0 0 54721 11270111317 16172 0ustar 0 0 /* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; class Drft{ int n; float[] trigcache; int[] splitcache; void backward(float[] data){ //System.err.println("Drft.backward"); if(n==1)return; drftb1(n,data,trigcache,trigcache,n,splitcache); } void init(int n){ //System.err.println("Drft.init"); this.n=n; trigcache=new float[3*n]; splitcache=new int[32]; fdrffti(n, trigcache, splitcache); } void clear(){ //System.err.println("Drft.clear"); if(trigcache!=null)trigcache=null; if(splitcache!=null)splitcache=null; // memset(l,0,sizeof(drft_lookup)); } static int[] ntryh = { 4,2,3,5 }; static float tpi = 6.28318530717958647692528676655900577f; static float hsqt2 = .70710678118654752440084436210485f; static float taui = .86602540378443864676372317075293618f; static float taur = -.5f; static float sqrt2 = 1.4142135623730950488016887242097f; static void drfti1(int n, float[] wa, int index, int[] ifac){ float arg,argh,argld,fi; int ntry=0,i,j=-1; int k1, l1, l2, ib; int ld, ii, ip, is, nq, nr; int ido, ipm, nfm1; int nl=n; int nf=0; int state=101; loop: while(true){ System.err.print(""); switch(state){ case 101: j++; if (j < 4) ntry=ntryh[j]; else ntry+=2; case 104: nq=nl/ntry; nr=nl-ntry*nq; if(nr!=0){ state=101; break; } nf++; ifac[nf+1]=ntry; nl=nq; if(ntry!=2){ state=107; break; } if(nf==1){ state=107; break; } for(i=1;i0){ // also handles the -1 out of data case int maxval=(1<m); for(int j=0; jn); for(int k=0; kn); return(0); } Object inverse1(Block vb, Object i, Object memo){ //System.err.println("Floor0.inverse "+i.getClass()+"]"); LookFloor0 look=(LookFloor0)i; InfoFloor0 info=look.vi; float[] lsp=null; if(memo instanceof float[]){ lsp=(float[])memo; } int ampraw=vb.opb.read(info.ampbits); if(ampraw>0){ // also handles the -1 out of data case int maxval=(1<n); for(int j=0; j>>=1; } return(ret); } static void lsp_to_lpc(float[] lsp, float[] lpc, int m){ int i,j,m2=m/2; float[] O=new float[m2]; float[] E=new float[m2]; float A; float[] Ae=new float[m2+1]; float[] Ao=new float[m2+1]; float B; float[] Be=new float[m2]; float[] Bo=new float[m2]; float temp; // even/odd roots setup for(i=0;im+1 must be less than l->ln, but guard in case we get a bad stream float[] lcurve=new float[Math.max(l.ln*2,l.m*2+2)]; if(amp==0){ //memset(curve,0,sizeof(float)*l->n); for(int j=0; j * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; import com.jcraft.jogg.*; class Floor1 extends FuncFloor{ static final int floor1_rangedb=140; static final int VIF_POSIT=63; void pack(Object i, Buffer opb){ InfoFloor1 info=(InfoFloor1)i; int count=0; int rangebits; int maxposit=info.postlist[1]; int maxclass=-1; /* save out partitions */ opb.write(info.partitions,5); /* only 0 to 31 legal */ for(int j=0;j=vi.books){ //goto err_out; info.free(); return(null); } for(int k=0;k<(1<=vi.books){ //goto err_out; info.free(); return(null); } } } /* read the post list */ info.mult=opb.read(2)+1; /* only 1,2,3,4 legal now */ rangebits=opb.read(4); for(int j=0,k=0;j=(1<info.postlist[sortpointer[k]]){ foo=sortpointer[k]; sortpointer[k]=sortpointer[j]; sortpointer[j]=foo; } } } /* points from sort order back to range number */ for(int j=0;j<_n;j++){ look.forward_index[j]=sortpointer[j]; } /* points from range order to sorted position */ for(int j=0;j<_n;j++){ look.reverse_index[look.forward_index[j]]=j; } /* we actually need the post values too */ for(int j=0;j<_n;j++){ look.sorted_index[j]=info.postlist[look.forward_index[j]]; } /* quantize values to multiplier spec */ switch(info.mult){ case 1: /* 1024 -> 256 */ look.quant_q=256; break; case 2: /* 1024 -> 128 */ look.quant_q=128; break; case 3: /* 1024 -> 86 */ look.quant_q=86; break; case 4: /* 1024 -> 64 */ look.quant_q=64; break; default: look.quant_q=-1; } /* discover our neighbors for decode where we don't use fit flags (that would push the neighbors outward) */ for(int j=0;j<_n-2;j++){ int lo=0; int hi=1; int lx=0; int hx=look.n; int currentx=info.postlist[j+2]; for(int k=0;klx && xcurrentx){ hi=k; hx=x; } } look.loneighbor[j]=lo; look.hineighbor[j]=hi; } return look; } void free_info(Object i){} void free_look(Object i){} void free_state(Object vs){} int forward(Block vb, Object i, float[] in, float[] out, Object vs){return 0;} Object inverse1(Block vb, Object ii, Object memo){ //System.err.println("Floor1.inverse "+i.getClass()+"]"); LookFloor1 look=(LookFloor1)ii; InfoFloor1 info=look.vi; CodeBook[] books=vb.vd.fullbooks; /* unpack wrapped/predicted values from stream */ if(vb.opb.read(1)==1){ int[] fit_value=null; if(memo instanceof int[]){ fit_value=(int[])memo; } if(fit_value==null || fit_value.length>>=csubbits; if(book>=0){ if((fit_value[j+k]=books[book].decode(vb.opb))==-1){ //goto eop; return(null); } } else{ fit_value[j+k]=0; } } j+=cdim; } /* unwrap positive values and reconsitute via linear interpolation */ for(int i=2;i=room){ if(hiroom>loroom){ val = val-loroom; } else{ val = -1-(val-hiroom); } } else{ if((val&1)!=0){ val= -((val+1)>>>1); } else{ val>>=1; } } fit_value[i]=val+predicted; fit_value[look.loneighbor[i-2]]&=0x7fff; fit_value[look.hineighbor[i-2]]&=0x7fff; } else{ fit_value[i]=predicted|0x8000; } } return(fit_value); } // eop: // return(NULL); return(null); } private static int render_point(int x0,int x1,int y0,int y1,int x){ y0&=0x7fff; /* mask off flag */ y1&=0x7fff; { int dy=y1-y0; int adx=x1-x0; int ady=Math.abs(dy); int err=ady*(x-x0); int off=(int)(err/adx); if(dy<0)return(y0-off); return(y0+off); } } int inverse2(Block vb, Object i, Object memo, float[] out){ LookFloor1 look=(LookFloor1)i; InfoFloor1 info=look.vi; int n=vb.vd.vi.blocksizes[vb.mode]/2; if(memo!=null){ /* render the lines */ int[] fit_value=(int[] )memo; int hx=0; int lx=0; int ly=fit_value[0]*info.mult; for(int j=1;j=adx){ err-=adx; y+=sy; } else{ y+=base; } d[x]*=FLOOR_fromdB_LOOKUP[y]; } } static int ilog(int v){ int ret=0; while(v!=0){ ret++; v>>>=1; } return(ret); } private static int ilog2(int v){ int ret=0; while(v>1){ ret++; v>>>=1; } return(ret); } } class InfoFloor1{ static final int VIF_POSIT=63; static final int VIF_CLASS=16; static final int VIF_PARTS=31; int partitions; /* 0 to 31 */ int[] partitionclass=new int[VIF_PARTS]; /* 0 to 15 */ int[] class_dim=new int[VIF_CLASS]; /* 1 to 8 */ int[] class_subs=new int[VIF_CLASS]; /* 0,1,2,3 (bits: 1< * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; import com.jcraft.jogg.*; abstract class FuncFloor{ // public static FuncFloor[] floor_P={new Floor0()}; public static FuncFloor[] floor_P={new Floor0(),new Floor1()}; abstract void pack(Object i, Buffer opb); abstract Object unpack(Info vi, Buffer opb); abstract Object look(DspState vd, InfoMode mi, Object i); // abstract Object state(Object i); abstract void free_info(Object i); abstract void free_look(Object i); abstract void free_state(Object vs); abstract int forward(Block vb, Object i, float[] in, float[] out, Object vs); // abstract int inverse(Block vb, Object i, float[] out); abstract Object inverse1(Block vb, Object i, Object memo); abstract int inverse2(Block vb, Object i, Object memo, float[] out); } cortado-0.6.0/src/com/jcraft/jorbis/FuncMapping.java100644 0 0 2726 11270111317 17460 0ustar 0 0 /* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; import com.jcraft.jogg.*; abstract class FuncMapping{ public static FuncMapping[] mapping_P={new Mapping0()}; abstract void pack(Info info , Object imap, Buffer buffer); abstract Object unpack(Info info , Buffer buffer); abstract Object look(DspState vd, InfoMode vm, Object m); abstract void free_info(Object imap); abstract void free_look(Object imap); // abstract int forward(Block vd, Object lm); abstract int inverse(Block vd, Object lm); } cortado-0.6.0/src/com/jcraft/jorbis/FuncResidue.java100644 0 0 3140 11270111317 17454 0ustar 0 0 /* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; import com.jcraft.jogg.*; abstract class FuncResidue{ public static FuncResidue[] residue_P={new Residue0(), new Residue1(), new Residue2()}; abstract void pack(Object vr, Buffer opb); abstract Object unpack(Info vi, Buffer opb); abstract Object look(DspState vd, InfoMode vm, Object vr); abstract void free_info(Object i); abstract void free_look(Object i); abstract int forward(Block vb,Object vl, float[][] in, int ch); // abstract int inverse(Block vb, Object vl, float[][] in, int ch); abstract int inverse(Block vb, Object vl, float[][] in, int[] nonzero,int ch); } cortado-0.6.0/src/com/jcraft/jorbis/FuncTime.java100644 0 0 2702 11270111317 16755 0ustar 0 0 /* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; import com.jcraft.jogg.*; abstract class FuncTime{ public static FuncTime[] time_P={new Time0()}; abstract void pack(Object i, Buffer opb); abstract Object unpack(Info vi , Buffer opb); abstract Object look(DspState vd, InfoMode vm, Object i); abstract void free_info(Object i); abstract void free_look(Object i); abstract int forward(Block vb, Object i); abstract int inverse(Block vb, Object i, float[] in, float[] out); } cortado-0.6.0/src/com/jcraft/jorbis/Info.java100644 0 0 32150 11270111317 16156 0ustar 0 0 /* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; import com.jcraft.jogg.*; public class Info{ private static final int OV_EBADPACKET=-136; private static final int OV_ENOTAUDIO=-135; private static byte[] _vorbis="vorbis".getBytes(); private static final int VI_TIMEB=1; // private static final int VI_FLOORB=1; private static final int VI_FLOORB=2; // private static final int VI_RESB=1; private static final int VI_RESB=3; private static final int VI_MAPB=1; private static final int VI_WINDOWB=1; public int version; public int channels; public int rate; // The below bitrate declarations are *hints*. // Combinations of the three values carry the following implications: // // all three set to the same value: // implies a fixed rate bitstream // only nominal set: // implies a VBR stream that averages the nominal bitrate. No hard // upper/lower limit // upper and or lower set: // implies a VBR bitstream that obeys the bitrate limits. nominal // may also be set to give a nominal rate. // none set: // the coder does not care to speculate. int bitrate_upper; int bitrate_nominal; int bitrate_lower; // Vorbis supports only short and long blocks, but allows the // encoder to choose the sizes int[] blocksizes=new int[2]; // modes are the primary means of supporting on-the-fly different // blocksizes, different channel mappings (LR or mid-side), // different residue backends, etc. Each mode consists of a // blocksize flag and a mapping (along with the mapping setup int modes; int maps; int times; int floors; int residues; int books; int psys; // encode only InfoMode[] mode_param=null; int[] map_type=null; Object[] map_param=null; int[] time_type=null; Object[] time_param=null; int[] floor_type=null; Object[] floor_param=null; int[] residue_type=null; Object[] residue_param=null; StaticCodeBook[] book_param=null; PsyInfo[] psy_param=new PsyInfo[64]; // encode only // for block long/sort tuning; encode only int envelopesa; float preecho_thresh; float preecho_clamp; // used by synthesis, which has a full, alloced vi public void init(){ rate=0; //memset(vi,0,sizeof(vorbis_info)); } public void clear(){ for(int i=0;ibook_param)free(vi->book_param); book_param=null; for(int i=0;ipsy_param)free(vi->psy_param); //memset(vi,0,sizeof(vorbis_info)); } // Header packing/unpacking int unpack_info(Buffer opb){ version=opb.read(32); if(version!=0)return(-1); channels=opb.read(8); rate=opb.read(32); bitrate_upper=opb.read(32); bitrate_nominal=opb.read(32); bitrate_lower=opb.read(32); blocksizes[0]=1<=VI_TIMEB){ //goto err_out; clear(); return(-1); } time_param[i]=FuncTime.time_P[time_type[i]].unpack(this, opb); if(time_param[i]==null){ //goto err_out; clear(); return(-1); } } // floor backend settings floors=opb.read(6)+1; if(floor_type==null || floor_type.length!=floors) floor_type=new int[floors]; if(floor_param==null || floor_param.length!=floors) floor_param=new Object[floors]; for(int i=0;i=VI_FLOORB){ //goto err_out; clear(); return(-1); } floor_param[i]=FuncFloor.floor_P[floor_type[i]].unpack(this,opb); if(floor_param[i]==null){ //goto err_out; clear(); return(-1); } } // residue backend settings residues=opb.read(6)+1; if(residue_type==null || residue_type.length!=residues) residue_type=new int[residues]; if(residue_param==null || residue_param.length!=residues) residue_param=new Object[residues]; for(int i=0;i=VI_RESB){ // goto err_out; clear(); return(-1); } residue_param[i]=FuncResidue.residue_P[residue_type[i]].unpack(this,opb); if(residue_param[i]==null){ // goto err_out; clear(); return(-1); } } // map backend settings maps=opb.read(6)+1; if(map_type==null || map_type.length!=maps) map_type=new int[maps]; if(map_param==null || map_param.length!=maps) map_param=new Object[maps]; for(int i=0;i=VI_MAPB){ // goto err_out; clear(); return(-1); } map_param[i]=FuncMapping.mapping_P[map_type[i]].unpack(this,opb); if(map_param[i]==null){ // goto err_out; clear(); return(-1); } } // mode settings modes=opb.read(6)+1; if(mode_param==null || mode_param.length!=modes) mode_param=new InfoMode[modes]; for(int i=0;i=VI_WINDOWB)|| (mode_param[i].transformtype>=VI_WINDOWB)|| (mode_param[i].mapping>=maps)){ // goto err_out; clear(); return(-1); } } if(opb.read(1)!=1){ //goto err_out; // top level EOP check clear(); return(-1); } return(0); // err_out: // vorbis_info_clear(vi); // return(-1); } // The Vorbis header is in three packets; the initial small packet in // the first page that identifies basic parameters, a second packet // with bitstream comments and a third packet that holds the // codebook. public int synthesis_headerin(Comment vc, Packet op){ Buffer opb=new Buffer(); if(op!=null){ opb.readinit(op.packet_base, op.packet, op.bytes); // Which of the three types of header is this? // Also verify header-ness, vorbis { byte[] buffer=new byte[6]; int packtype=opb.read(8); //memset(buffer,0,6); opb.read(buffer,6); if(buffer[0]!='v' || buffer[1]!='o' || buffer[2]!='r' || buffer[3]!='b' || buffer[4]!='i' || buffer[5]!='s'){ // not a vorbis header return(-1); } switch(packtype){ case 0x01: // least significant *bit* is read first if(op.b_o_s==0){ // Not the initial packet return(-1); } if(rate!=0){ // previously initialized info header return(-1); } return(unpack_info(opb)); case 0x03: // least significant *bit* is read first if(rate==0){ // um... we didn't get the initial header return(-1); } return(vc.unpack(opb)); case 0x05: // least significant *bit* is read first if(rate==0 || vc.vendor==null){ // um... we didn;t get the initial header or comments yet return(-1); } return(unpack_books(opb)); default: // Not a valid vorbis header type //return(-1); break; } } } return(-1); } // pack side int pack_info(Buffer opb){ // preamble opb.write(0x01,8); opb.write(_vorbis); // basic information about the stream opb.write(0x00,32); opb.write(channels,8); opb.write(rate,32); opb.write(bitrate_upper,32); opb.write(bitrate_nominal,32); opb.write(bitrate_lower,32); opb.write(ilog2(blocksizes[0]),4); opb.write(ilog2(blocksizes[1]),4); opb.write(1,1); return(0); } int pack_books(Buffer opb){ opb.write(0x05,8); opb.write(_vorbis); // books opb.write(books-1,8); for(int i=0;icodec_setup; Buffer opb=new Buffer(); // synchronized(opb_blocksize){ int mode; opb.readinit(op.packet_base, op.packet, op.bytes); /* Check the packet type */ if(opb.read(1)!=0){ /* Oops. This is not an audio data packet */ return(OV_ENOTAUDIO); } { int modebits=0; int v=modes; while(v>1){ modebits++; v>>>=1; } /* read our mode and pre/post windowsize */ mode=opb.read(modebits); } if(mode==-1)return(OV_EBADPACKET); return(blocksizes[mode_param[mode].blockflag]); // } } private static int ilog2(int v){ int ret=0; while(v>1){ ret++; v>>>=1; } return(ret); } public String toString(){ return "version:"+new Integer(version)+ ", channels:"+new Integer(channels)+ ", rate:"+new Integer(rate)+ ", bitrate:"+new Integer(bitrate_upper)+","+ new Integer(bitrate_nominal)+","+ new Integer(bitrate_lower); } } cortado-0.6.0/src/com/jcraft/jorbis/InfoMode.java100644 0 0 2140 11270111317 16737 0ustar 0 0 /* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; class InfoMode{ int blockflag; int windowtype; int transformtype; int mapping; } cortado-0.6.0/src/com/jcraft/jorbis/JOrbisException.java100644 0 0 2255 11270111317 20315 0ustar 0 0 /* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; public class JOrbisException extends Exception { public JOrbisException () { super(); } public JOrbisException (String s) { super ("JOrbis: "+s); } } cortado-0.6.0/src/com/jcraft/jorbis/Lookup.java100644 0 0 17267 11270111317 16550 0ustar 0 0 /* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; class Lookup{ static final int COS_LOOKUP_SZ=128; static final float[] COS_LOOKUP={ +1.0000000000000f,+0.9996988186962f,+0.9987954562052f,+0.9972904566787f, +0.9951847266722f,+0.9924795345987f,+0.9891765099648f,+0.9852776423889f, +0.9807852804032f,+0.9757021300385f,+0.9700312531945f,+0.9637760657954f, +0.9569403357322f,+0.9495281805930f,+0.9415440651830f,+0.9329927988347f, +0.9238795325113f,+0.9142097557035f,+0.9039892931234f,+0.8932243011955f, +0.8819212643484f,+0.8700869911087f,+0.8577286100003f,+0.8448535652497f, +0.8314696123025f,+0.8175848131516f,+0.8032075314806f,+0.7883464276266f, +0.7730104533627f,+0.7572088465065f,+0.7409511253550f,+0.7242470829515f, +0.7071067811865f,+0.6895405447371f,+0.6715589548470f,+0.6531728429538f, +0.6343932841636f,+0.6152315905806f,+0.5956993044924f,+0.5758081914178f, +0.5555702330196f,+0.5349976198871f,+0.5141027441932f,+0.4928981922298f, +0.4713967368260f,+0.4496113296546f,+0.4275550934303f,+0.4052413140050f, +0.3826834323651f,+0.3598950365350f,+0.3368898533922f,+0.3136817403989f, +0.2902846772545f,+0.2667127574749f,+0.2429801799033f,+0.2191012401569f, +0.1950903220161f,+0.1709618887603f,+0.1467304744554f,+0.1224106751992f, +0.0980171403296f,+0.0735645635997f,+0.0490676743274f,+0.0245412285229f, +0.0000000000000f,-0.0245412285229f,-0.0490676743274f,-0.0735645635997f, -0.0980171403296f,-0.1224106751992f,-0.1467304744554f,-0.1709618887603f, -0.1950903220161f,-0.2191012401569f,-0.2429801799033f,-0.2667127574749f, -0.2902846772545f,-0.3136817403989f,-0.3368898533922f,-0.3598950365350f, -0.3826834323651f,-0.4052413140050f,-0.4275550934303f,-0.4496113296546f, -0.4713967368260f,-0.4928981922298f,-0.5141027441932f,-0.5349976198871f, -0.5555702330196f,-0.5758081914178f,-0.5956993044924f,-0.6152315905806f, -0.6343932841636f,-0.6531728429538f,-0.6715589548470f,-0.6895405447371f, -0.7071067811865f,-0.7242470829515f,-0.7409511253550f,-0.7572088465065f, -0.7730104533627f,-0.7883464276266f,-0.8032075314806f,-0.8175848131516f, -0.8314696123025f,-0.8448535652497f,-0.8577286100003f,-0.8700869911087f, -0.8819212643484f,-0.8932243011955f,-0.9039892931234f,-0.9142097557035f, -0.9238795325113f,-0.9329927988347f,-0.9415440651830f,-0.9495281805930f, -0.9569403357322f,-0.9637760657954f,-0.9700312531945f,-0.9757021300385f, -0.9807852804032f,-0.9852776423889f,-0.9891765099648f,-0.9924795345987f, -0.9951847266722f,-0.9972904566787f,-0.9987954562052f,-0.9996988186962f, -1.0000000000000f, }; /* interpolated lookup based cos function, domain 0 to PI only */ static float coslook(float a){ double d=a*(.31830989*(float)COS_LOOKUP_SZ); int i=(int)d; return COS_LOOKUP[i]+ ((float)(d-i))*(COS_LOOKUP[i+1]-COS_LOOKUP[i]); } static final int INVSQ_LOOKUP_SZ=32; static final float[] INVSQ_LOOKUP={ 1.414213562373f,1.392621247646f,1.371988681140f,1.352246807566f, 1.333333333333f,1.315191898443f,1.297771369046f,1.281025230441f, 1.264911064067f,1.249390095109f,1.234426799697f,1.219988562661f, 1.206045378311f,1.192569588000f,1.179535649239f,1.166919931983f, 1.154700538379f,1.142857142857f,1.131370849898f,1.120224067222f, 1.109400392450f,1.098884511590f,1.088662107904f,1.078719779941f, 1.069044967650f,1.059625885652f,1.050451462878f,1.041511287847f, 1.032795558989f,1.024295039463f,1.016001016002f,1.007905261358f, 1.000000000000f, }; /* interpolated 1./sqrt(p) where .5 <= p < 1. */ static float invsqlook(float a){ // System.out.println(a); double d=a*(2.f*(float)INVSQ_LOOKUP_SZ)-(float)INVSQ_LOOKUP_SZ; int i=(int)d; return INVSQ_LOOKUP[i]+ ((float)(d-i))*(INVSQ_LOOKUP[i+1]-INVSQ_LOOKUP[i]); } static final int INVSQ2EXP_LOOKUP_MIN=-32; static final int INVSQ2EXP_LOOKUP_MAX=32; static final float[] INVSQ2EXP_LOOKUP={ 65536.f, 46340.95001f, 32768.f, 23170.47501f, 16384.f, 11585.2375f, 8192.f, 5792.618751f, 4096.f, 2896.309376f, 2048.f, 1448.154688f, 1024.f, 724.0773439f, 512.f, 362.038672f, 256.f, 181.019336f, 128.f, 90.50966799f, 64.f, 45.254834f, 32.f, 22.627417f, 16.f, 11.3137085f, 8.f, 5.656854249f, 4.f, 2.828427125f, 2.f, 1.414213562f, 1.f, 0.7071067812f, 0.5f, 0.3535533906f, 0.25f, 0.1767766953f, 0.125f, 0.08838834765f, 0.0625f, 0.04419417382f, 0.03125f, 0.02209708691f, 0.015625f, 0.01104854346f, 0.0078125f, 0.005524271728f, 0.00390625f, 0.002762135864f, 0.001953125f, 0.001381067932f, 0.0009765625f, 0.000690533966f, 0.00048828125f, 0.000345266983f, 0.000244140625f,0.0001726334915f,0.0001220703125f,8.631674575e-05f, 6.103515625e-05f,4.315837288e-05f,3.051757812e-05f,2.157918644e-05f, 1.525878906e-05f, }; /* interpolated 1./sqrt(p) where .5 <= p < 1. */ static float invsq2explook(int a){ return INVSQ2EXP_LOOKUP[a-INVSQ2EXP_LOOKUP_MIN]; } static final int FROMdB_LOOKUP_SZ=35; static final int FROMdB2_LOOKUP_SZ=32; static final int FROMdB_SHIFT=5; static final int FROMdB2_SHIFT=3; static final int FROMdB2_MASK=31; static final float[] FROMdB_LOOKUP={ 1.f, 0.6309573445f, 0.3981071706f, 0.2511886432f, 0.1584893192f, 0.1f, 0.06309573445f, 0.03981071706f, 0.02511886432f, 0.01584893192f, 0.01f, 0.006309573445f, 0.003981071706f, 0.002511886432f, 0.001584893192f, 0.001f, 0.0006309573445f,0.0003981071706f,0.0002511886432f,0.0001584893192f, 0.0001f,6.309573445e-05f,3.981071706e-05f,2.511886432e-05f, 1.584893192e-05f, 1e-05f,6.309573445e-06f,3.981071706e-06f, 2.511886432e-06f,1.584893192e-06f, 1e-06f,6.309573445e-07f, 3.981071706e-07f,2.511886432e-07f,1.584893192e-07f, }; static final float[] FROMdB2_LOOKUP={ 0.9928302478f, 0.9786445908f, 0.9646616199f, 0.9508784391f, 0.9372921937f, 0.92390007f, 0.9106992942f, 0.8976871324f, 0.8848608897f, 0.8722179097f, 0.8597555737f, 0.8474713009f, 0.835362547f, 0.8234268041f, 0.8116616003f, 0.8000644989f, 0.7886330981f, 0.7773650302f, 0.7662579617f, 0.755309592f, 0.7445176537f, 0.7338799116f, 0.7233941627f, 0.7130582353f, 0.7028699885f, 0.6928273125f, 0.6829281272f, 0.6731703824f, 0.6635520573f, 0.6540711597f, 0.6447257262f, 0.6355138211f, }; /* interpolated lookup based fromdB function, domain -140dB to 0dB only */ static float fromdBlook(float a){ int i=(int)(a*((float)(-(1<=(FROMdB_LOOKUP_SZ<>>FROMdB_SHIFT]*FROMdB2_LOOKUP[i&FROMdB2_MASK]); } } cortado-0.6.0/src/com/jcraft/jorbis/Lpc.java100644 0 0 13607 11270111317 16007 0ustar 0 0 /* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; class Lpc{ // en/decode lookups Drft fft=new Drft();; int ln; int m; // Autocorrelation LPC coeff generation algorithm invented by // N. Levinson in 1947, modified by J. Durbin in 1959. // Input : n elements of time doamin data // Output: m lpc coefficients, excitation energy static float lpc_from_data(float[] data, float[] lpc,int n,int m){ float[] aut=new float[m+1]; float error; int i,j; // autocorrelation, p+1 lag coefficients j=m+1; while(j--!=0){ float d=0; for(i=j;iln*2); for(int i=0; i * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; /* function: LSP (also called LSF) conversion routines The LSP generation code is taken (with minimal modification) from "On the Computation of the LSP Frequencies" by Joseph Rothweiler , available at: http://www2.xtdl.com/~rothwlr/lsfpaper/lsfpage.html ********************************************************************/ class Lsp{ static final float M_PI=(float)(3.1415926539); static void lsp_to_curve(float[] curve, int[] map, int n, int ln, float[] lsp, int m, float amp, float ampoffset){ int i; float wdel=M_PI/ln; for(i=0;i=0x7f800000||(ix==0)){ // 0,inf,nan } else{ if(ix<0x00800000){ // subnormal q*=3.3554432000e+07; // 0x4c000000 hx=Float.floatToIntBits(q); ix=0x7fffffff&hx; qexp=-25; } qexp += ((ix>>>23)-126); hx=(hx&0x807fffff)|0x3f000000; q=Float.intBitsToFloat(hx); } q=Lookup.fromdBlook(amp* Lookup.invsqlook(q)* Lookup.invsq2explook(qexp+m)-ampoffset); do{curve[i++]*=q;} // do{curve[i++]=q;} while(i * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; import com.jcraft.jogg.*; class Mapping0 extends FuncMapping{ static int seq=0; void free_info(Object imap){}; void free_look(Object imap){ /* LookMapping0 l=(LookMapping0)imap; InfoMapping0 info=l.map; if(l!=null){ for(int i=0;idecay[i]); l.decay[i]=null; } //free(l->decay); l.decay=null; } //free(l->time_func); //free(l->floor_func); //free(l->residue_func); //free(l->time_look); //free(l->floor_look); //free(l->residue_look); //f(l->psy_look)free(l->psy_look); l.time_func=null; l.floor_func=null; l.residue_func=null; l.time_look=null; l.floor_look=null; l.residue_look=null; //memset(l,0,sizeof(vorbis_look_mapping0)); //free(l); */ } Object look(DspState vd, InfoMode vm, Object m){ //System.err.println("Mapping0.look"); Info vi=vd.vi; LookMapping0 look=new LookMapping0(); InfoMapping0 info=look.map=(InfoMapping0)m; look.mode=vm; look.time_look=new Object[info.submaps]; look.floor_look=new Object[info.submaps]; look.residue_look=new Object[info.submaps]; /* if(vd.analysisp!=0){ look.floor_state=new Object[vi.channels]; } if(vi.psys!=0){ look.psy_look=new PsyLook[info.submaps]; for(int i=0; ipsy[0] != info->psy[1]){ int psynum=info->psy[0]; look->psy_look[0]=_ogg_calloc(1,sizeof(vorbis_look_psy)); _vp_psy_init(look->psy_look[0],ci->psy_param[psynum], ci->psy_g_param, ci->blocksizes[vm->blockflag]/2,vi->rate); psynum=info->psy[1]; look->psy_look[1]=_ogg_calloc(1,sizeof(vorbis_look_psy)); _vp_psy_init(look->psy_look[1],ci->psy_param[psynum], ci->psy_g_param, ci->blocksizes[vm->blockflag]/2,vi->rate); }else{ int psynum=info->psy[0]; look->psy_look[0]=_ogg_calloc(1,sizeof(vorbis_look_psy)); look->psy_look[1]=look->psy_look[0]; _vp_psy_init(look->psy_look[0],ci->psy_param[psynum], ci->psy_g_param, ci->blocksizes[vm->blockflag]/2,vi->rate); } */ } look.ch=vi.channels; // if(vd->analysisp)drft_init(&look->fft_look,ci->blocksizes[vm->blockflag]); return(look); //return null; } void pack(Info vi, Object imap, Buffer opb){ InfoMapping0 info=(InfoMapping0)imap; /* another 'we meant to do it this way' hack... up to beta 4, we packed 4 binary zeros here to signify one submapping in use. We now redefine that to mean four bitflags that indicate use of deeper features; bit0:submappings, bit1:coupling, bit2,3:reserved. This is backward compatable with all actual uses of the beta code. */ if(info.submaps>1){ opb.write(1,1); opb.write(info.submaps-1,4); } else{ opb.write(0,1); } if(info.coupling_steps>0){ opb.write(1,1); opb.write(info.coupling_steps-1,8); for(int i=0;i1){ for(int i=0;i=vi.channels || testA>=vi.channels){ //goto err_out; info.free(); return(null); } } } if(opb.read(2)>0){ /* 2,3:reserved */ //goto err_out; info.free(); return(null); } if(info.submaps>1){ for(int i=0;i=info.submaps){ //goto err_out; info.free(); return(null); } } } for(int i=0;i=vi.times){ //goto err_out; info.free(); return(null); } info.floorsubmap[i]=opb.read(8); if(info.floorsubmap[i]>=vi.floors){ //goto err_out; info.free(); return(null); } info.residuesubmap[i]=opb.read(8); if(info.residuesubmap[i]>=vi.residues){ //goto err_out; info.free(); return(null); } } return info; //err_out: //free_info(info); //return(NULL); } /* // no time mapping implementation for now static int seq=0; int forward(Block vb, Object l){ DspState vd=vb.vd; Info vi=vd.vi; LookMapping0 look=(LookMapping0)l; InfoMapping0 info=look.map; InfoMode mode=look.mode; int n=vb.pcmend; float[] window=vd.window[vb.W][vb.lW][vb.nW][mode.windowtype]; float[][] pcmbundle=new float[vi.channles][]; int[] nonzero=new int[vi.channels]; // time domain pre-window: NONE IMPLEMENTED // window the PCM data: takes PCM vector, vb; modifies PCM vector for(int i=0;isequence) // memset(decay,0,n*sizeof(float)/2); // perform psychoacoustics; do masking _vp_compute_mask(look.psy_look[submap],pcm,floor,decay); _analysis_output("mdct",seq,pcm,n/2,0,1); _analysis_output("lmdct",seq,pcm,n/2,0,0); _analysis_output("prefloor",seq,floor,n/2,0,1); // perform floor encoding nonzero[i]=look.floor_func[submap]. forward(vb,look.floor_look[submap],floor,floor,look.floor_state[i]); _analysis_output("floor",seq,floor,n/2,0,1); // apply the floor, do optional noise levelling _vp_apply_floor(look->psy_look+submap,pcm,floor); _analysis_output("res",seq++,pcm,n/2,0,0); } // perform residue encoding with residue mapping; this is // multiplexed. All the channels belonging to one submap are // encoded (values interleaved), then the next submap, etc for(int i=0;i=0;i--){ float[] pcmM=vb.pcm[info.coupling_mag[i]]; float[] pcmA=vb.pcm[info.coupling_ang[i]]; for(int j=0;j0){ if(ang>0){ pcmM[j]=mag; pcmA[j]=mag-ang; } else{ pcmA[j]=mag; pcmM[j]=mag+ang; } } else{ if(ang>0){ pcmM[j]=mag; pcmA[j]=mag+ang; } else{ pcmA[j]=mag; pcmM[j]=mag-ang; } } } } // /* compute and apply spectral envelope */ for(int i=0;i0)v--; while(v>0){ ret++; v>>>=1; } return(ret); } } class InfoMapping0{ int submaps; // <= 16 int[] chmuxlist=new int[256]; // up to 256 channels in a Vorbis stream int[] timesubmap=new int[16]; // [mux] int[] floorsubmap=new int[16]; // [mux] submap to floors int[] residuesubmap=new int[16];// [mux] submap to residue int[] psysubmap=new int[16]; // [mux]; encode only int coupling_steps; int[] coupling_mag=new int[256]; int[] coupling_ang=new int[256]; void free(){ chmuxlist=null; timesubmap=null; floorsubmap=null; residuesubmap=null; psysubmap=null; coupling_mag=null; coupling_ang=null; } } class LookMapping0{ InfoMode mode; InfoMapping0 map; Object[] time_look; Object[] floor_look; Object[] floor_state; Object[] residue_look; PsyLook[] psy_look; FuncTime[] time_func; FuncFloor[] floor_func; FuncResidue[] residue_func; int ch; float[][] decay; int lastframe; // if a different mode is called, we need to // invalidate decay and floor state } cortado-0.6.0/src/com/jcraft/jorbis/Mdct.java100644 0 0 11436 11274615664 16200 0ustar 0 0 /* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; class Mdct{ int n; int log2n; float[] trig; int[] bitrev; float scale; void init(int n){ bitrev=new int[n/4]; trig=new float[n+n/4]; log2n=(int)Math.rint(Math.log(n)/Math.log(2)); this.n=n; int AE=0; int AO=1; int BE=AE+n/2; int BO=BE+1; int CE=BE+n/2; int CO=CE+1; // trig lookups... for(int i=0;i>>j!=0;j++) if(((msb>>>j)&i)!=0)acc|=1<>>1; int n4=n>>>2; int n8=n>>>3; // rotate + step 1 { int inO=1; int xO=0; int A=n2; int i; for(i=0;i>>(i+2); int k1=1<<(i+3); int wbase=n2-2; A=0; float[] temp; for(int r=0;r<(k0>>>2);r++){ int w1=wbase; w2=w1-(k0>>1); float AEv= trig[A],wA; float AOv= trig[A+1],wB; wbase-=2; k0++; for(int s=0;s<(2< * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; // psychoacoustic setup class PsyInfo{ int athp; int decayp; int smoothp; int noisefitp; int noisefit_subblock; float noisefit_threshdB; float ath_att; int tonemaskp; float[] toneatt_125Hz=new float[5]; float[] toneatt_250Hz=new float[5]; float[] toneatt_500Hz=new float[5]; float[] toneatt_1000Hz=new float[5]; float[] toneatt_2000Hz=new float[5]; float[] toneatt_4000Hz=new float[5]; float[] toneatt_8000Hz=new float[5]; int peakattp; float[] peakatt_125Hz=new float[5]; float[] peakatt_250Hz=new float[5]; float[] peakatt_500Hz=new float[5]; float[] peakatt_1000Hz=new float[5]; float[] peakatt_2000Hz=new float[5]; float[] peakatt_4000Hz=new float[5]; float[] peakatt_8000Hz=new float[5]; int noisemaskp; float[] noiseatt_125Hz=new float[5]; float[] noiseatt_250Hz=new float[5]; float[] noiseatt_500Hz=new float[5]; float[] noiseatt_1000Hz=new float[5]; float[] noiseatt_2000Hz=new float[5]; float[] noiseatt_4000Hz=new float[5]; float[] noiseatt_8000Hz=new float[5]; float max_curve_dB; float attack_coeff; float decay_coeff; void free(){} } cortado-0.6.0/src/com/jcraft/jorbis/PsyLook.java100644 0 0 17102 11270111317 16663 0ustar 0 0 /* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; class PsyLook { int n; PsyInfo vi; float[][][] tonecurves; float[][] peakatt; float[][][] noisecurves; float[] ath; int[] octave; void init(PsyInfo vi, int n, int rate){ /* float rate2=rate/2.; //memset(p,0,sizeof(vorbis_look_psy)); ath=new float[n]; octave=new int[n]; this.vi=vi; this.n=n; // set up the lookups for a given blocksize and sample rate // Vorbis max sample rate is limited by 26 Bark (54kHz) set_curve(ATH_Bark_dB, ath,n,rate); for(int i=0;i12)oc=12; octave[i]=oc; } tonecurves=malloc(13*sizeof(float **)); noisecurves=malloc(13*sizeof(float **)); peakatt=malloc(7*sizeof(float *)); for(int i=0;i<13;i++){ tonecurves[i]=malloc(9*sizeof(float *)); noisecurves[i]=malloc(9*sizeof(float *)); } for(i=0;i<7;i++) peakatt[i]=malloc(5*sizeof(float)); for(i=0;i<13;i++){ for(j=0;j<9;j++){ tonecurves[i][j]=malloc(EHMER_MAX*sizeof(float)); noisecurves[i][j]=malloc(EHMER_MAX*sizeof(float)); } } // OK, yeah, this was a silly way to do it memcpy(tonecurves[0][2],tone_125_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[0][4],tone_125_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[0][6],tone_125_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[0][8],tone_125_100dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[2][2],tone_250_40dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[2][4],tone_250_60dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[2][6],tone_250_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[2][8],tone_250_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[4][2],tone_500_40dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[4][4],tone_500_60dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[4][6],tone_500_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[4][8],tone_500_100dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[6][2],tone_1000_40dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[6][4],tone_1000_60dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[6][6],tone_1000_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[6][8],tone_1000_100dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[8][2],tone_2000_40dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[8][4],tone_2000_60dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[8][6],tone_2000_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[8][8],tone_2000_100dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[10][2],tone_4000_40dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[10][4],tone_4000_60dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[10][6],tone_4000_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[10][8],tone_4000_100dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[12][2],tone_4000_40dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[12][4],tone_4000_60dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[12][6],tone_8000_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(tonecurves[12][8],tone_8000_100dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[0][2],noise_500_60dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[0][4],noise_500_60dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[0][6],noise_500_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[0][8],noise_500_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[2][2],noise_500_60dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[2][4],noise_500_60dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[2][6],noise_500_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[2][8],noise_500_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[4][2],noise_500_60dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[4][4],noise_500_60dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[4][6],noise_500_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[4][8],noise_500_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[6][2],noise_1000_60dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[6][4],noise_1000_60dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[6][6],noise_1000_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[6][8],noise_1000_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[8][2],noise_2000_60dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[8][4],noise_2000_60dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[8][6],noise_2000_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[8][8],noise_2000_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[10][2],noise_4000_60dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[10][4],noise_4000_60dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[10][6],noise_4000_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[10][8],noise_4000_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[12][2],noise_4000_60dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[12][4],noise_4000_60dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[12][6],noise_4000_80dB_SL,sizeof(float)*EHMER_MAX); memcpy(noisecurves[12][8],noise_4000_80dB_SL,sizeof(float)*EHMER_MAX); setup_curve(tonecurves[0],0,vi.toneatt_125Hz); setup_curve(tonecurves[2],2,vi.toneatt_250Hz); setup_curve(tonecurves[4],4,vi.toneatt_500Hz); setup_curve(tonecurves[6],6,vi.toneatt_1000Hz); setup_curve(tonecurves[8],8,vi.toneatt_2000Hz); setup_curve(tonecurves[10],10,vi.toneatt_4000Hz); setup_curve(tonecurves[12],12,vi.toneatt_8000Hz); setup_curve(noisecurves[0],0,vi.noiseatt_125Hz); setup_curve(noisecurves[2],2,vi.noiseatt_250Hz); setup_curve(noisecurves[4],4,vi.noiseatt_500Hz); setup_curve(noisecurves[6],6,vi.noiseatt_1000Hz); setup_curve(noisecurves[8],8,vi.noiseatt_2000Hz); setup_curve(noisecurves[10],10,vi.noiseatt_4000Hz); setup_curve(noisecurves[12],12,vi.noiseatt_8000Hz); for(i=1;i<13;i+=2){ for(j=0;j<9;j++){ interp_curve_dB(tonecurves[i][j], tonecurves[i-1][j], tonecurves[i+1][j],.5); interp_curve_dB(noisecurves[i][j], noisecurves[i-1][j], noisecurves[i+1][j],.5); } } for(i=0;i<5;i++){ peakatt[0][i]=fromdB(vi.peakatt_125Hz[i]); peakatt[1][i]=fromdB(vi.peakatt_250Hz[i]); peakatt[2][i]=fromdB(vi.peakatt_500Hz[i]); peakatt[3][i]=fromdB(vi.peakatt_1000Hz[i]); peakatt[4][i]=fromdB(vi.peakatt_2000Hz[i]); peakatt[5][i]=fromdB(vi.peakatt_4000Hz[i]); peakatt[6][i]=fromdB(vi.peakatt_8000Hz[i]); } */ } } cortado-0.6.0/src/com/jcraft/jorbis/Residue0.java100644 0 0 27620 11274362076 16767 0ustar 0 0 /* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; import com.jcraft.jogg.*; class Residue0 extends FuncResidue{ void pack(Object vr, Buffer opb){ InfoResidue0 info=(InfoResidue0)vr; int acc=0; opb.write(info.begin,24); opb.write(info.end,24); opb.write(info.grouping-1,24); /* residue vectors to group and code with a partitioned book */ opb.write(info.partitions-1,6); /* possible partition choices */ opb.write(info.groupbook,8); /* group huffman book */ /* secondstages is a bitmask; as encoding progresses pass by pass, a bitmask of one indicates this partition class has bits to write this pass */ for(int j=0;j3){ /* yes, this is a minor hack due to not thinking ahead */ opb.write(info.secondstages[j],3); opb.write(1,1); opb.write(info.secondstages[j]>>>3,5); } else{ opb.write(info.secondstages[j],4); /* trailing zero */ } acc+=icount(info.secondstages[j]); } for(int j=0;j=vi.books){ free_info(info); return(null); } for(int j=0;j=vi.books){ free_info(info); return(null); } } return(info); // errout: // free_info(info); // return(NULL); } Object look(DspState vd, InfoMode vm, Object vr){ InfoResidue0 info=(InfoResidue0)vr; LookResidue0 look=new LookResidue0(); int acc=0; int dim; int maxstage=0; look.info=info; look.map=vm.mapping; look.parts=info.partitions; look.fullbooks=vd.fullbooks; look.phrasebook=vd.fullbooks[info.groupbook]; dim=look.phrasebook.dim; look.partbooks=new int[look.parts][]; for(int j=0;jmaxstage)maxstage=stages; look.partbooks[j]=new int[stages]; for(int k=0; k>>=1; } return(ret); } private static int icount(int v){ int ret=0; while(v!=0){ ret+=(v&1); v>>>=1; } return(ret); } } class LookResidue0 { InfoResidue0 info; int map; int parts; int stages; CodeBook[] fullbooks; CodeBook phrasebook; int[][] partbooks; // CodeBook[][] partbooks; int partvals; int[][] decodemap; int postbits; int phrasebits; // int[][] frames; int frames; } class InfoResidue0{ // block-partitioned VQ coded straight residue int begin; int end; // first stage (lossless partitioning) int grouping; // group n vectors per partition int partitions; // possible codebooks for a partition int groupbook; // huffbook for partitioning int[] secondstages=new int[64]; // expanded out to pointers in lookup int[] booklist=new int[256]; // list of second stage books // encode-only heuristic settings float[] entmax=new float[64]; // book entropy threshholds float[] ampmax=new float[64]; // book amp threshholds int[] subgrp=new int[64]; // book heuristic subgroup size int[] blimit=new int[64]; // subgroup position limits } cortado-0.6.0/src/com/jcraft/jorbis/Residue1.java100644 0 0 2772 11274615664 16755 0ustar 0 0 /* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; class Residue1 extends Residue0{ int forward(Block vb,Object vl, float[][] in, int ch){ System.err.println("Residue0.forward: not implemented"); return 0; } int inverse(Block vb, Object vl, float[][] in, int[] nonzero, int ch){ //System.err.println("Residue0.inverse"); int used=0; for(int i=0; i * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; class Residue2 extends Residue0{ int forward(Block vb,Object vl, float[][] in, int ch){ System.err.println("Residue0.forward: not implemented"); return 0; } int inverse(Block vb, Object vl, float[][] in, int[] nonzero, int ch){ //System.err.println("Residue0.inverse"); int i=0; for(i=0;i * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; import com.jcraft.jogg.*; class StaticCodeBook{ int dim; // codebook dimensions (elements per vector) int entries; // codebook entries int[] lengthlist; // codeword lengths in bits // mapping int maptype; // 0=none // 1=implicitly populated values from map column // 2=listed arbitrary values // The below does a linear, single monotonic sequence mapping. int q_min; // packed 32 bit float; quant value 0 maps to minval int q_delta; // packed 32 bit float; val 1 - val 0 == delta int q_quant; // bits: 0 < quant <= 16 int q_sequencep; // bitflag // additional information for log (dB) mapping; the linear mapping // is assumed to actually be values in dB. encodebias is used to // assign an error weight to 0 dB. We have two additional flags: // zeroflag indicates if entry zero is to represent -Inf dB; negflag // indicates if we're to represent negative linear values in a // mirror of the positive mapping. int[] quantlist; // map == 1: (int)(entries/dim) element column map // map == 2: list of dim*entries quantized entry vals // encode helpers EncodeAuxNearestMatch nearest_tree; EncodeAuxThreshMatch thresh_tree; StaticCodeBook(){} StaticCodeBook(int dim, int entries, int[] lengthlist, int maptype, int q_min, int q_delta, int q_quant, int q_sequencep, int[] quantlist, //EncodeAuxNearestmatch nearest_tree, Object nearest_tree, // EncodeAuxThreshmatch thresh_tree, Object thresh_tree ){ this(); this.dim=dim; this.entries=entries; this.lengthlist=lengthlist; this.maptype=maptype; this.q_min=q_min; this.q_delta=q_delta; this.q_quant=q_quant; this.q_sequencep=q_sequencep; this.quantlist=quantlist; } int pack(Buffer opb){ int i; boolean ordered=false; opb.write(0x564342,24); opb.write(dim, 16); opb.write(entries, 24); // pack the codewords. There are two packings; length ordered and // length random. Decide between the two now. for(i=1;i_last){ for(int j=_last;j<_this;j++){ opb.write(i-count,ilog(entries-count)); count=i; } } } opb.write(i-count,ilog(entries-count)); } else{ // length random. Again, we don't code the codeword itself, just // the length. This time, though, we have to encode each length opb.write(0,1); // unordered // algortihmic mapping has use for 'unused entries', which we tag // here. The algorithmic mapping happens as usual, but the unused // entry has no codeword. for(i=0;ientries/c->dim) quantized values for // building a full value list algorithmically (square lattice) quantvals=maptype1_quantvals(); break; case 2: // every value (c->entries*c->dim total) specified explicitly quantvals=entries*dim; break; } // quantized values for(i=0;ibim <= b->entries // treat the above as an initial guess while(true){ int acc=1; int acc1=1; for(int i=0;ientries){ return(vals); } else{ if(acc>entries){ vals--; } else{ vals++; } } } } void clear(){ // if(quantlist!=null)free(b->quantlist); // if(lengthlist!=null)free(b->lengthlist); // if(nearest_tree!=null){ // free(b->nearest_tree->ptr0); // free(b->nearest_tree->ptr1); // free(b->nearest_tree->p); // free(b->nearest_tree->q); // memset(b->nearest_tree,0,sizeof(encode_aux_nearestmatch)); // free(b->nearest_tree); // } // if(thresh_tree!=null){ // free(b->thresh_tree->quantthresh); // free(b->thresh_tree->quantmap); // memset(b->thresh_tree,0,sizeof(encode_aux_threshmatch)); // free(b->thresh_tree); // } // memset(b,0,sizeof(static_codebook)); } // unpack the quantized list of values for encode/decode // we need to deal with two map types: in map type 1, the values are // generated algorithmically (each column of the vector counts through // the values in the quant vector). in map type 2, all the values came // in in an explicit list. Both value lists must be unpacked float[] unquantize(){ if(maptype==1 || maptype==2){ int quantvals; float mindel=float32_unpack(q_min); float delta=float32_unpack(q_delta); float[] r=new float[entries*dim]; //System.err.println("q_min="+q_min+", mindel="+mindel); // maptype 1 and 2 both use a quantized value vector, but // different sizes switch(maptype){ case 1: // most of the time, entries%dimensions == 0, but we need to be // well defined. We define that the possible vales at each // scalar is values == entries/dim. If entries%dim != 0, we'll // have 'too few' values (values*dim "+val+" | ");} val=Math.abs(val)*delta+mindel+last; if(q_sequencep!=0)last=val; r[j*dim+k]=val; //if((j*dim+k)==0){System.err.println(" $ r[0] -> "+r[0]+" | ");} } } //System.err.println("\nr[0]="+r[0]); } return(r); } return(null); } private static int ilog(int v){ int ret=0; while(v!=0){ ret++; v>>>=1; } return(ret); } // 32 bit float (not IEEE; nonnormalized mantissa + // biased exponent) : neeeeeee eeemmmmm mmmmmmmm mmmmmmmm // Why not IEEE? It's just not that important here. static final int VQ_FEXP=10; static final int VQ_FMAN=21; static final int VQ_FEXP_BIAS=768; // bias toward values smaller than 1. // doesn't currently guard under/overflow static long float32_pack(float val){ int sign=0; int exp; int mant; if(val<0){ sign=0x80000000; val= -val; } exp=(int)Math.floor(Math.log(val)/Math.log(2)); mant=(int)Math.rint(Math.pow(val,(VQ_FMAN-1)-exp)); exp=(exp+VQ_FEXP_BIAS)<>>VQ_FMAN; //System.err.println("mant="+mant+", sign="+sign+", exp="+exp); //if(sign!=0.0)mant= -mant; if((val&0x80000000)!=0)mant= -mant; //System.err.println("mant="+mant); return(ldexp(mant,((int)exp)-(VQ_FMAN-1)-VQ_FEXP_BIAS)); } static float ldexp(float foo, int e){ return (float)(foo*Math.pow(2, e)); } /* // TEST // Unit tests of the dequantizer; this stuff will be OK // cross-platform, I simply want to be sure that special mapping cases // actually work properly; a bug could go unnoticed for a while // cases: // // no mapping // full, explicit mapping // algorithmic mapping // // nonsequential // sequential static int[] full_quantlist1={0,1,2,3, 4,5,6,7, 8,3,6,1}; static int[] partial_quantlist1={0,7,2}; // no mapping static StaticCodeBook test1=new StaticCodeBook(4,16,null, 0,0,0,0,0, null,null,null); static float[] test1_result=null; // linear, full mapping, nonsequential static StaticCodeBook test2=new StaticCodeBook(4,3,null, 2,-533200896,1611661312,4,0, full_quantlist1, null, null); static float[] test2_result={-3,-2,-1,0, 1,2,3,4, 5,0,3,-2}; // linear, full mapping, sequential static StaticCodeBook test3=new StaticCodeBook(4,3,null, 2, -533200896,1611661312,4,1, full_quantlist1,null, null); static float[] test3_result={-3,-5,-6,-6, 1,3,6,10, 5,5,8,6}; // linear, algorithmic mapping, nonsequential static StaticCodeBook test4=new StaticCodeBook(3,27,null, 1,-533200896,1611661312,4,0, partial_quantlist1,null,null); static float[] test4_result={-3,-3,-3, 4,-3,-3, -1,-3,-3, -3, 4,-3, 4, 4,-3, -1, 4,-3, -3,-1,-3, 4,-1,-3, -1,-1,-3, -3,-3, 4, 4,-3, 4, -1,-3, 4, -3, 4, 4, 4, 4, 4, -1, 4, 4, -3,-1, 4, 4,-1, 4, -1,-1, 4, -3,-3,-1, 4,-3,-1, -1,-3,-1, -3, 4,-1, 4, 4,-1, -1, 4,-1, -3,-1,-1, 4,-1,-1, -1,-1,-1}; // linear, algorithmic mapping, sequential static StaticCodeBook test5=new StaticCodeBook(3,27,null, 1,-533200896,1611661312,4,1, partial_quantlist1,null,null); static float[] test5_result={-3,-6,-9, 4, 1,-2, -1,-4,-7, -3, 1,-2, 4, 8, 5, -1, 3, 0, -3,-4,-7, 4, 3, 0, -1,-2,-5, -3,-6,-2, 4, 1, 5, -1,-4, 0, -3, 1, 5, 4, 8,12, -1, 3, 7, -3,-4, 0, 4, 3, 7, -1,-2, 2, -3,-6,-7, 4, 1, 0, -1,-4,-5, -3, 1, 0, 4, 8, 7, -1, 3, 2, -3,-4,-5, 4, 3, 2, -1,-2,-3}; void run_test(float[] comp){ float[] out=unquantize(); if(comp!=null){ if(out==null){ System.err.println("_book_unquantize incorrectly returned NULL"); System.exit(1); } for(int i=0;i.0001){ System.err.println("disagreement in unquantized and reference data:\nposition "+i+": "+out[i]+" != "+comp[i]); System.exit(1); } } } else{ if(out!=null){ System.err.println("_book_unquantize returned a value array:\n correct result should have been NULL"); System.exit(1); } } } public static void main(String[] arg){ // run the nine dequant tests, and compare to the hand-rolled results System.err.print("Dequant test 1... "); test1.run_test(test1_result); System.err.print("OK\nDequant test 2... "); test2.run_test(test2_result); System.err.print("OK\nDequant test 3... "); test3.run_test(test3_result); System.err.print("OK\nDequant test 4... "); test4.run_test(test4_result); System.err.print("OK\nDequant test 5... "); test5.run_test(test5_result); System.err.print("OK\n\n"); } */ } cortado-0.6.0/src/com/jcraft/jorbis/Time0.java100644 0 0 2603 11270111317 16221 0ustar 0 0 /* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; import com.jcraft.jogg.*; class Time0 extends FuncTime{ void pack(Object i, Buffer opb){} Object unpack(Info vi , Buffer opb){return "";} Object look(DspState vd, InfoMode mi, Object i){return "";} void free_info(Object i){} void free_look(Object i){} int forward(Block vb, Object i){return 0;} int inverse(Block vb, Object i, float[] in, float[] out){return 0;} } cortado-0.6.0/src/com/jcraft/jorbis/VorbisFile.java100644 0 0 107152 11270111317 17354 0ustar 0 0 /* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk * * Many thanks to * Monty and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; import com.jcraft.jogg.*; import java.io.InputStream; public class VorbisFile{ static final int CHUNKSIZE=8500; static final int SEEK_SET=0; static final int SEEK_CUR=1; static final int SEEK_END=2; static final int OV_FALSE=-1; static final int OV_EOF=-2; static final int OV_HOLE=-3; static final int OV_EREAD=-128; static final int OV_EFAULT=-129; static final int OV_EIMPL=-130; static final int OV_EINVAL=-131; static final int OV_ENOTVORBIS=-132; static final int OV_EBADHEADER=-133; static final int OV_EVERSION=-134; static final int OV_ENOTAUDIO=-135; static final int OV_EBADPACKET=-136; static final int OV_EBADLINK=-137; static final int OV_ENOSEEK=-138; InputStream datasource; boolean seekable=false; long offset; long end; SyncState oy=new SyncState(); int links; long[] offsets; long[] dataoffsets; int[] serialnos; long[] pcmlengths; Info[] vi; Comment[] vc; // Decoding working state local storage long pcm_offset; boolean decode_ready=false; int current_serialno; int current_link; float bittrack; float samptrack; StreamState os=new StreamState(); // take physical pages, weld into a logical // stream of packets DspState vd=new DspState(); // central working state for // the packet->PCM decoder Block vb=new Block(vd); // local working space for packet->PCM decode //ov_callbacks callbacks; public VorbisFile(String file) throws JOrbisException { super(); InputStream is=null; /* try{ is=new java.io.FileInputStream(file);} catch(Exception e){ throw new JOrbisException("VorbisFile: "+e.toString()); } */ try{ is=new SeekableInputStream(file);} catch(Exception e){ throw new JOrbisException("VorbisFile: "+e.toString()); } int ret=open(is, null, 0); if(ret==-1){ throw new JOrbisException("VorbisFile: open return -1"); } } public VorbisFile(InputStream is, byte[] initial, int ibytes) throws JOrbisException { super(); int ret=open(is, initial, ibytes); if(ret==-1){ } } private int get_data(){ int index=oy.buffer(CHUNKSIZE); byte[] buffer=oy.data; // int bytes=callbacks.read_func(buffer, index, 1, CHUNKSIZE, datasource); int bytes=0; try{ bytes=datasource.read(buffer, index, CHUNKSIZE); } catch(Exception e){ System.err.println(e); return OV_EREAD; } oy.wrote(bytes); if(bytes==-1){ // System.out.println("bytes="+bytes); bytes=0; } return bytes; } private void seek_helper(long offst){ //callbacks.seek_func(datasource, offst, SEEK_SET); fseek(datasource, offst, SEEK_SET); this.offset=offst; oy.reset(); } private int get_next_page(Page page, long boundary){ if(boundary>0) boundary+=offset; while(true){ int more; if(boundary>0 && offset>=boundary)return OV_FALSE; more=oy.pageseek(page); if(more<0){offset-=more;} else{ if(more==0){ if(boundary==0)return OV_FALSE; // if(get_data()<=0)return -1; int ret=get_data(); if(ret==0) return OV_EOF; if(ret<0) return OV_EREAD; } else{ int ret=(int)offset; //!!! offset+=more; return ret; } } } } private int get_prev_page(Page page){ long begin=offset; //!!! int ret; int offst=-1; while(offst==-1){ begin-=CHUNKSIZE; if(begin<0) begin=0; seek_helper(begin); while(offset=0)next=ret; } else{ searched=ret+page.header_len+page.body_len; } } seek_helper(next); ret=get_next_page(page, -1); if(ret==OV_EREAD) return OV_EREAD; if(searched>=end || ret==-1){ links=m+1; offsets=new long[m+2]; offsets[m+1]=searched; } else{ ret=bisect_forward_serialno(next, offset, end, page.serialno(), m+1); if(ret==OV_EREAD)return OV_EREAD; } offsets[m]=begin; return 0; } // uses the local ogg_stream storage in vf; this is important for // non-streaming input sources int fetch_headers(Info vi, Comment vc, int[] serialno, Page og_ptr){ //System.err.println("fetch_headers"); Page og=new Page(); Packet op=new Packet(); int ret; if(og_ptr==null){ ret=get_next_page(og, CHUNKSIZE); if(ret==OV_EREAD)return OV_EREAD; if(ret<0) return OV_ENOTVORBIS; og_ptr=og; } if(serialno!=null)serialno[0]=og_ptr.serialno(); os.init(og_ptr.serialno()); // extract the initial header from the first page and verify that the // Ogg bitstream is in fact Vorbis data vi.init(); vc.init(); int i=0; while(i<3){ os.pagein(og_ptr); while(i<3){ int result=os.packetout(op); if(result==0)break; if(result==-1){ System.err.println("Corrupt header in logical bitstream."); //goto bail_header; vi.clear(); vc.clear(); os.clear(); return -1; } if(vi.synthesis_headerin(vc, op)!=0){ System.err.println("Illegal header in logical bitstream."); //goto bail_header; vi.clear(); vc.clear(); os.clear(); return -1; } i++; } if(i<3) if(get_next_page(og_ptr, 1)<0){ System.err.println("Missing header in logical bitstream."); //goto bail_header; vi.clear(); vc.clear(); os.clear(); return -1; } } return 0; // bail_header: // vorbis_info_clear(vi); // vorbis_comment_clear(vc); // ogg_stream_clear(&vf->os); // return -1; } // last step of the OggVorbis_File initialization; get all the // vorbis_info structs and PCM positions. Only called by the seekable // initialization (local stream storage is hacked slightly; pay // attention to how that's done) void prefetch_all_headers(Info first_i,Comment first_c, int dataoffset){ Page og=new Page(); int ret; vi=new Info[links]; vc=new Comment[links]; dataoffsets=new long[links]; pcmlengths=new long[links]; serialnos=new int[links]; for(int i=0;ivi+i,first_i,sizeof(vorbis_info)); vc[i]=first_c; //memcpy(vf->vc+i,first_c,sizeof(vorbis_comment)); dataoffsets[i]=dataoffset; } else{ // seek to the location of the initial header seek_helper(offsets[i]); //!!! if(fetch_headers(vi[i], vc[i], null, null)==-1){ System.err.println("Error opening logical bitstream #"+(i+1)+"\n"); dataoffsets[i]=-1; } else{ dataoffsets[i]=offset; os.clear(); } } // get the serial number and PCM length of this link. To do this, // get the last page of the stream { long end=offsets[i+1]; //!!! seek_helper(end); while(true){ ret=get_prev_page(og); if(ret==-1){ // this should not be possible System.err.println("Could not find last page of logical "+ "bitstream #"+(i)+"\n"); vi[i].clear(); vc[i].clear(); break; } if(og.granulepos()!=-1){ serialnos[i]=og.serialno(); pcmlengths[i]=og.granulepos(); break; } } } } } int make_decode_ready(){ if(decode_ready)System.exit(1); vd.synthesis_init(vi[0]); vb.init(vd); decode_ready=true; return(0); } int open_seekable(){ Info initial_i=new Info(); Comment initial_c=new Comment(); int serialno; long end; int ret; int dataoffset; Page og=new Page(); // is this even vorbis...? int[] foo=new int[1]; ret=fetch_headers(initial_i, initial_c, foo, null); serialno=foo[0]; dataoffset=(int)offset; //!! os.clear(); if(ret==-1)return(-1); // we can seek, so set out learning all about this file seekable=true; //(callbacks.seek_func)(datasource, 0, SEEK_END); fseek(datasource, 0, SEEK_END); //offset=end=(callbacks.tell_func)(datasource); offset=ftell(datasource); end=offset; // We get the offset for the last page of the physical bitstream. // Most OggVorbis files will contain a single logical bitstream end=get_prev_page(og); // moer than one logical bitstream? if(og.serialno()!=serialno){ // Chained bitstream. Bisect-search each logical bitstream // section. Do so based on serial number only if(bisect_forward_serialno(0,0,end+1,serialno,0)<0){ clear(); return OV_EREAD; } } else{ // Only one logical bitstream if(bisect_forward_serialno(0,end,end+1,serialno,0)<0){ clear(); return OV_EREAD; } } prefetch_all_headers(initial_i, initial_c, dataoffset); return(raw_seek(0)); } int open_nonseekable(){ //System.err.println("open_nonseekable"); // we cannot seek. Set up a 'single' (current) logical bitstream entry links=1; vi=new Info[links]; vi[0]=new Info(); // ?? vc=new Comment[links]; vc[0]=new Comment(); // ?? bug? // Try to fetch the headers, maintaining all the storage int[]foo=new int[1]; if(fetch_headers(vi[0], vc[0], foo, null)==-1)return(-1); current_serialno=foo[0]; make_decode_ready(); return 0; } // clear out the current logical bitstream decoder void decode_clear(){ os.clear(); vd.clear(); vb.clear(); decode_ready=false; bittrack=0.f; samptrack=0.f; } // fetch and process a packet. Handles the case where we're at a // bitstream boundary and dumps the decoding machine. If the decoding // machine is unloaded, it loads it. It also keeps pcm_offset up to // date (seek and read both use this. seek uses a special hack with // readp). // // return: -1) hole in the data (lost packet) // 0) need more date (only if readp==0)/eof // 1) got a packet int process_packet(int readp){ Page og=new Page(); // handle one packet. Try to fetch it from current stream state // extract packets from page while(true){ // process a packet if we can. If the machine isn't loaded, // neither is a page if(decode_ready){ Packet op=new Packet(); int result=os.packetout(op); long granulepos; // if(result==-1)return(-1); // hole in the data. For now, swallow // and go. We'll need to add a real // error code in a bit. if(result>0){ // got a packet. process it granulepos=op.granulepos; if(vb.synthesis(op)==0){ // lazy check for lazy // header handling. The // header packets aren't // audio, so if/when we // submit them, // vorbis_synthesis will // reject them // suck in the synthesis data and track bitrate { int oldsamples=vd.synthesis_pcmout(null, null); vd.synthesis_blockin(vb); samptrack+=vd.synthesis_pcmout(null, null)-oldsamples; bittrack+=op.bytes*8; } // update the pcm offset. if(granulepos!=-1 && op.e_o_s==0){ int link=(seekable?current_link:0); int samples; // this packet has a pcm_offset on it (the last packet // completed on a page carries the offset) After processing // (above), we know the pcm position of the *last* sample // ready to be returned. Find the offset of the *first* // // As an aside, this trick is inaccurate if we begin // reading anew right at the last page; the end-of-stream // granulepos declares the last frame in the stream, and the // last packet of the last page may be a partial frame. // So, we need a previous granulepos from an in-sequence page // to have a reference point. Thus the !op.e_o_s clause above samples=vd.synthesis_pcmout(null, null); granulepos-=samples; for(int i=0;icallbacks.close_func)(vf->datasource); //memset(vf,0,sizeof(OggVorbis_File)); return(0); } static int fseek(InputStream fis, //int64_t off, long off, int whence){ if(fis instanceof SeekableInputStream){ SeekableInputStream sis=(SeekableInputStream)fis; try{ if(whence==SEEK_SET){ sis.seek(off); } else if(whence==SEEK_END){ sis.seek(sis.getLength()-off); } else{ System.out.println("seek: "+whence+" is not supported"); } } catch(Exception e){ } return 0; } try{ if(whence==0){ fis.reset(); } fis.skip(off); } catch(Exception e){return -1;} return 0; } static long ftell(InputStream fis){ try{ if(fis instanceof SeekableInputStream){ SeekableInputStream sis=(SeekableInputStream)fis; return (sis.tell()); } } catch(Exception e){ } return 0; } // inspects the OggVorbis file and finds/documents all the logical // bitstreams contained in it. Tries to be tolerant of logical // bitstream sections that are truncated/woogie. // // return: -1) error // 0) OK int open(InputStream is, byte[] initial, int ibytes){ //callbacks callbacks = { // (size_t (*)(void *, size_t, size_t, void *)) fread, // (int (*)(void *, int64_t, int)) _fseek, // (int (*)(void *)) fclose, // (long (*)(void *)) ftell // }; return open_callbacks(is, initial, ibytes//, callbacks ); } int open_callbacks(InputStream is, byte[] initial, int ibytes//, callbacks callbacks ){ int ret; datasource=is; //callbacks = _callbacks; // init the framing state oy.init(); // perhaps some data was previously read into a buffer for testing // against other stream types. Allow initialization from this // previously read data (as we may be reading from a non-seekable // stream) if(initial!=null){ int index=oy.buffer(ibytes); System.arraycopy(initial, 0, oy.data, index, ibytes); oy.wrote(ibytes); } // can we seek? Stevens suggests the seek test was portable if(is instanceof SeekableInputStream){ ret=open_seekable(); } else{ ret=open_nonseekable(); } if(ret!=0){ datasource=null; clear(); } return(ret); } // How many logical bitstreams in this physical bitstream? public int streams(){ return links; } // Is the FILE * associated with vf seekable? public boolean seekable(){ return seekable; } // returns the bitrate for a given logical bitstream or the entire // physical bitstream. If the file is open for random access, it will // find the *actual* average bitrate. If the file is streaming, it // returns the nominal bitrate (if set) else the average of the // upper/lower bounds (if set) else -1 (unset). // // If you want the actual bitrate field settings, get them from the // vorbis_info structs public int bitrate(int i){ if(i>=links)return(-1); if(!seekable && i!=0)return(bitrate(0)); if(i<0){ long bits=0; for(int j=0;j0){ return vi[i].bitrate_nominal; } else{ if(vi[i].bitrate_upper>0){ if(vi[i].bitrate_lower>0){ return (vi[i].bitrate_upper+vi[i].bitrate_lower)/2; }else{ return vi[i].bitrate_upper; } } return(-1); } } } } // returns the actual bitrate since last call. returns -1 if no // additional data to offer since last call (or at beginning of stream) public int bitrate_instant(){ int _link=(seekable?current_link:0); if(samptrack==0)return(-1); int ret=(int)(bittrack/samptrack*vi[_link].rate+.5); bittrack=0.f; samptrack=0.f; return(ret); } public int serialnumber(int i){ if(i>=links)return(-1); if(!seekable && i>=0)return(serialnumber(-1)); if(i<0){ return(current_serialno); } else{ return(serialnos[i]); } } // returns: total raw (compressed) length of content if i==-1 // raw (compressed) length of that logical bitstream for i==0 to n // -1 if the stream is not seekable (we can't know the length) public long raw_total(int i){ if(!seekable || i>=links)return(-1); if(i<0){ long acc=0; // bug? for(int j=0;j=links)return(-1); if(i<0){ long acc=0; for(int j=0;j=links)return(-1); if(i<0){ float acc=0; for(int j=0;joffsets[links]){ //goto seek_error; pcm_offset=-1; decode_clear(); return -1; } // clear out decoding machine state pcm_offset=-1; decode_clear(); // seek seek_helper(pos); // we need to make sure the pcm_offset is set. We use the // _fetch_packet helper to process one packet with readp set, then // call it until it returns '0' with readp not set (the last packet // from a page has the 'granulepos' field set, and that's how the // helper updates the offset switch(process_packet(1)){ case 0: // oh, eof. There are no packets remaining. Set the pcm offset to // the end of file pcm_offset=pcm_total(-1); return(0); case -1: // error! missing data or invalid bitstream structure //goto seek_error; pcm_offset=-1; decode_clear(); return -1; default: // all OK break; } while(true){ switch(process_packet(0)){ case 0: // the offset is set. If it's a bogus bitstream with no offset // information, it's not but that's not our fault. We still run // gracefully, we're just missing the offset return(0); case -1: // error! missing data or invalid bitstream structure //goto seek_error; pcm_offset=-1; decode_clear(); return -1; default: // continue processing packets break; } } // seek_error: // dump the machine so we're in a known state //pcm_offset=-1; //decode_clear(); //return -1; } // seek to a sample offset relative to the decompressed pcm stream // returns zero on success, nonzero on failure public int pcm_seek(long pos){ int link=-1; long total=pcm_total(-1); if(!seekable)return(-1); // don't dump machine if we can't seek if(pos<0 || pos>total){ //goto seek_error; pcm_offset=-1; decode_clear(); return -1; } // which bitstream section does this pcm offset occur in? for(link=links-1;link>=0;link--){ total-=pcmlengths[link]; if(pos>=total)break; } // search within the logical bitstream for the page with the highest // pcm_pos preceeding (or equal to) pos. There is a danger here; // missing pages or incorrect frame number information in the // bitstream could make our task impossible. Account for that (it // would be an error condition) { long target=pos-total; long end=offsets[link+1]; long begin=offsets[link]; int best=(int)begin; Page og=new Page(); while(begin=pos){ //goto seek_error; pcm_offset=-1; decode_clear(); return -1; } if(pos>pcm_total(-1)){ //goto seek_error; pcm_offset=-1; decode_clear(); return -1; } // discard samples until we reach the desired position. Crossing a // logical bitstream boundary with abandon is OK. while(pcm_offsettarget)samples=target; vd.synthesis_read(samples); pcm_offset+=samples; if(samplestime_total){ //goto seek_error; pcm_offset=-1; decode_clear(); return -1; } // which bitstream section does this time offset occur in? for(link=links-1;link>=0;link--){ pcm_total-=pcmlengths[link]; time_total-=time_total(link); if(seconds>=time_total)break; } // enough information to convert time offset to pcm offset { long target=(long)(pcm_total+(seconds-time_total)*vi[link].rate); return(pcm_seek(target)); } //seek_error: // dump machine so we're in a known state //pcm_offset=-1; //decode_clear(); //return -1; } // tell the current stream offset cursor. Note that seek followed by // tell will likely not give the set offset due to caching public long raw_tell(){ return(offset); } // return PCM offset (sample) of next PCM sample to be read public long pcm_tell(){ return(pcm_offset); } // return time offset (seconds) of next PCM sample to be read public float time_tell(){ // translate time to PCM position and call pcm_seek int link=-1; long pcm_total=0; float time_total=0.f; if(seekable){ pcm_total=pcm_total(-1); time_total=time_total(-1); // which bitstream section does this time offset occur in? for(link=links-1;link>=0;link--){ pcm_total-=pcmlengths[link]; time_total-=time_total(link); if(pcm_offset>=pcm_total)break; } } return((float)time_total+(float)(pcm_offset-pcm_total)/vi[link].rate); } // link: -1) return the vorbis_info struct for the bitstream section // currently being decoded // 0-n) to request information for a specific bitstream section // // In the case of a non-seekable bitstream, any call returns the // current bitstream. NULL in the case that the machine is not // initialized public Info getInfo(int link){ if(seekable){ if(link<0){ if(decode_ready){ return vi[current_link]; } else{ return null; } } else{ if(link>=links){ return null; } else{ return vi[link]; } } } else{ if(decode_ready){ return vi[0]; } else{ return null; } } } public Comment getComment(int link){ if(seekable){ if(link<0){ if(decode_ready){ return vc[current_link]; } else{ return null; } } else{ if(link>=links){ return null;} else{ return vc[link]; } } } else{ if(decode_ready){ return vc[0]; } else{ return null; } } } int host_is_big_endian() { return 1; // short pattern = 0xbabe; // unsigned char *bytewise = (unsigned char *)&pattern; // if (bytewise[0] == 0xba) return 1; // assert(bytewise[0] == 0xbe); // return 0; } // up to this point, everything could more or less hide the multiple // logical bitstream nature of chaining from the toplevel application // if the toplevel application didn't particularly care. However, at // the point that we actually read audio back, the multiple-section // nature must surface: Multiple bitstream sections do not necessarily // have to have the same number of channels or sampling rate. // // read returns the sequential logical bitstream number currently // being decoded along with the PCM data in order that the toplevel // application can take action on channel/sample rate changes. This // number will be incremented even for streamed (non-seekable) streams // (for seekable streams, it represents the actual logical bitstream // index within the physical bitstream. Note that the accessor // functions above are aware of this dichotomy). // // input values: buffer) a buffer to hold packed PCM data for return // length) the byte length requested to be placed into buffer // bigendianp) should the data be packed LSB first (0) or // MSB first (1) // word) word size for output. currently 1 (byte) or // 2 (16 bit short) // // return values: -1) error/hole in data // 0) EOF // n) number of bytes of PCM actually returned. The // below works on a packet-by-packet basis, so the // return length is not related to the 'length' passed // in, just guaranteed to fit. // // *section) set to the logical bitstream number int read(byte[] buffer,int length, int bigendianp, int word, int sgned, int[] bitstream){ int host_endian = host_is_big_endian(); int index=0; while(true){ if(decode_ready){ float[][] pcm; float[][][] _pcm=new float[1][][]; int[] _index=new int[getInfo(-1).channels]; int samples=vd.synthesis_pcmout(_pcm, _index); pcm=_pcm[0]; if(samples!=0){ // yay! proceed to pack data into the byte buffer int channels=getInfo(-1).channels; int bytespersample=word * channels; if(samples>length/bytespersample)samples=length/bytespersample; // a tight loop to pack each size { int val; if(word==1){ int off=(sgned!=0?0:128); for(int j=0;j127)val=127; else if(val<-128)val=-128; buffer[index++]=(byte)(val+off); } } } else{ int off=(sgned!=0?0:32768); if(host_endian==bigendianp){ if(sgned!=0){ for(int i=0;i32767)val=32767; else if(val<-32768)val=-32768; buffer[dest]=(byte)(val>>>8); buffer[dest+1]=(byte)(val); dest+=channels*2; } } } else{ for(int i=0;i32767)val=32767; else if(val<-32768)val=-32768; buffer[dest]=(byte)((val+off)>>>8); buffer[dest+1]=(byte)(val+off); dest+=channels*2; } } } } else if(bigendianp!=0){ for(int j=0;j32767)val=32767; else if(val<-32768)val=-32768; val+=off; buffer[index++]=(byte)(val>>>8); buffer[index++]=(byte)val; } } } else{ //int val; for(int j=0;j32767)val=32767; else if(val<-32768)val=-32768; val+=off; buffer[index++]=(byte)val; buffer[index++]=(byte)(val>>>8); } } } } } vd.synthesis_read(samples); pcm_offset+=samples; if(bitstream!=null)bitstream[0]=current_link; return(samples*bytespersample); } } // suck in another packet switch(process_packet(1)){ case 0: return(0); case -1: return -1; default: break; } } } public Info[] getInfo(){return vi;} public Comment[] getComment(){return vc;} public static void main(String[] arg){ try{ VorbisFile foo=new VorbisFile(arg[0]); int links=foo.streams(); System.out.println("links="+links); Comment[] comment=foo.getComment(); Info[] info=foo.getInfo(); for(int i=0; iPQR S =T =UV WX YZ [\]G =^_` ab cdefg Ph ij kl mnopqrst u vwx 'yz{| +m} .~ . W W 3 3 3k()VCodemain([Ljava/lang/String;)V StackMapTableQupdate5(Ljava/io/File;Ljava/lang/String;Ljava/lang/String;)Vw getBranch"(Ljava/io/File;)Ljava/lang/String; getRevision{} ?@ java/io/File. ? LK JKrevision   branch GH6Usage: java GetSourceInfo [revision | branch | update]#src/com/fluendo/jst/SourceInfo.java ? (unknown) 3Unknown revision information, leaving existing file.svn0No top-level .svn directory, leaving file alone.java/lang/StringBuilder!Updating SourceInfo file, branch  , revision java/io/FileWriter ?Ppackage com.fluendo.jst; public class SourceInfo { public String revision = "";  public String branch = "  public SourceInfo() {  } } @java/io/IOException+Error: Unable to write to SourceInfo.java:  Wikimediajava/io/FileReader .svn/entriesjava/io/LineNumberReader ? ?@A* BCA|ZYL+M+N*;*2 , *2  - *2  +,-  D,EFF GHAٻY*N,+-  Y*  Y,+ Y-:Y+ ,!"#$%&": Y() h'D-ErI JKA* LKAL+YY*,-M.Y,/N-0:12L-0W-0W-0:3Y456:Y78L: : ; M Y<,) +>gj9'D$jEFMNFO BIcortado-0.6.0/scripts/GetSourceInfo.java100755 0 0 6060 11274360126 15354 0ustar 0 0 import java.io.*; public class GetSourceInfo { public static void main(String args[]) { File topSrcDir = new File("."); String revision = GetSourceInfo.getRevision(topSrcDir); String branch = GetSourceInfo.getBranch(topSrcDir); if (args.length != 0) { if (args[0].equals("revision")) { System.out.println(revision); return; } else if (args[0].equals("branch")) { System.out.println(branch); return; } else if (args[0].equals("update")) { GetSourceInfo.update(topSrcDir, revision, branch); return; } } System.out.println("Usage: java GetSourceInfo [revision | branch | update]"); } // Update jst/SourceInfo.java public static void update(File topSrcDir, String revision, String branch) { File targetFile = new File(topSrcDir, "src/com/fluendo/jst/SourceInfo.java"); // If branch and revision are unknown, and the file already exists, leave it if (branch.equals("(unknown)") && revision.equals("(unknown)") && targetFile.exists()) { System.out.println("Unknown revision information, leaving existing file"); return; } if ( ! (new File(topSrcDir, ".svn")).exists() ) { System.out.println("No top-level .svn directory, leaving file alone."); return; } System.out.println("Updating SourceInfo file, branch " + branch + ", revision " + revision); try { FileWriter fw = new FileWriter(targetFile); fw.write( "package com.fluendo.jst;\n" + "\n" + "public class SourceInfo\n" + "{\n" + " public String revision = \"" + revision + "\";\n" + " public String branch = \"" + branch + "\";\n" + "\n" + " public SourceInfo() {\n" + " }\n" + "}\n" ); fw.close(); } catch (IOException e) { System.out.println("Error: Unable to write to SourceInfo.java: " + e.getLocalizedMessage()); } } public static String getBranch(File topSrcDir) { return "Wikimedia"; } public static String getRevision(File topSrcDir) { // Code here is based on MediaWiki's SpecialVersion::getSvnRevision(), // except that it only works with 1.4+, because I couldn't be bothered // working out how to read that XML file in Java. [TS] String revision = "(unknown)"; try { FileReader fr = new FileReader(new File(topSrcDir, ".svn/entries")); LineNumberReader lnr = new LineNumberReader(fr); String line = lnr.readLine(); if (!line.startsWith(" $targetfile < $topsrcdir/cortado.spec echo Version: $VERSION echo Release: $RELEASE import java.io.*; public class GetSourceInfo { public static void main(String args[]) { File topSrcDir = new File("."); String revision = GetSourceInfo.getRevision(topSrcDir); String branch = GetSourceInfo.getBranch(topSrcDir); if (args.length != 0) { if (args[0].equals("revision")) { System.out.println(revision); return; } else if (args[0].equals("branch")) { System.out.println(branch); return; } else if (args[0].equals("update")) { GetSourceInfo.update(topSrcDir, revision, branch); return; } } System.out.println("Usage: java GetSourceInfo [revision | branch | update]"); } // Update jst/SourceInfo.java public static void update(File topSrcDir, String revision, String branch) { File targetFile = new File(topSrcDir, "src/com/fluendo/jst/SourceInfo.java"); // If branch and revision are unknown, and the file already exists, leave it if (branch.equals("(unknown)") && revision.equals("(unknown)") && targetFile.exists()) { System.out.println("Unknown revision information, leaving existing file"); return; } if ( ! (new File(topSrcDir, ".svn")).exists() ) { System.out.println("No top-level .svn directory, leaving file alone."); return; } System.out.println("Updating SourceInfo file, branch " + branch + ", revision " + revision); try { FileWriter fw = new FileWriter(targetFile); fw.write( "package com.fluendo.jst;\n" + "\n" + "public class SourceInfo\n" + "{\n" + " public String revision = \"" + revision + "\";\n" + " public String branch = \"" + branch + "\";\n" + "\n" + " public SourceInfo() {\n" + " }\n" + "}\n" ); fw.close(); } catch (IOException e) { System.out.println("Error: Unable to write to SourceInfo.java: " + e.getLocalizedMessage()); } } public static String getBranch(File topSrcDir) { return "Wikimedia"; } public static String getRevision(File topSrcDir) { // Code here is based on MediaWiki's SpecialVersion::getSvnRevision(), // except that it only works with 1.4+, because I couldn't be bothered // working out how to read that XML file in Java. [TS] String revision = "(unknown)"; try { FileReader fr = new FileReader(new File(topSrcDir, ".svn/entries")); LineNumberReader lnr = new LineNumberReader(fr); String line = lnr.readLine(); if (!line.startsWith(" $targetfile < $topsrcdir/cortado.spec echo Version: $VERSION echo Release: $RELEASE