* Deleted useless com.jme3.video package
git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8318 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
3f95a0ca2f
commit
b1e46de5ee
engine/src/jheora/com/jme3/video
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2010 jMonkeyEngine
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.jme3.video;
|
||||
|
||||
@Deprecated
|
||||
public interface Clock {
|
||||
|
||||
public static final long MILLIS_TO_NANOS = 1000000;
|
||||
public static final long SECONDS_TO_NANOS = 1000000000;
|
||||
|
||||
public long getTime();
|
||||
public double getTimeSeconds();
|
||||
}
|
@ -1,177 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2010 jMonkeyEngine
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.jme3.video;
|
||||
|
||||
@Deprecated
|
||||
public final class RingBuffer {
|
||||
|
||||
private final int bufSize;
|
||||
private final byte[] buf;
|
||||
private final Object lock = new Object();
|
||||
|
||||
private volatile int writePos;
|
||||
private volatile int readPos;
|
||||
|
||||
// private volatile boolean eof;
|
||||
private volatile long totalRead = 0,
|
||||
totalWritten = 0;
|
||||
|
||||
public RingBuffer(int size) {
|
||||
bufSize = size;
|
||||
buf = new byte[size];
|
||||
}
|
||||
|
||||
public int remainingForWrite() {
|
||||
if (writePos < readPos) return readPos - writePos - 1;
|
||||
if (writePos == readPos) return bufSize - 1;
|
||||
return bufSize - (writePos - readPos) - 1;
|
||||
}
|
||||
|
||||
public void write(byte[] data, int offset, int length) {
|
||||
if (length == 0) return;
|
||||
|
||||
synchronized (lock) {
|
||||
while (remainingForWrite() < length) {
|
||||
System.out.println("Warning: Audio decoder starved, waiting for player");
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
// copy data
|
||||
if (writePos >= readPos) {
|
||||
int l = Math.min(length, bufSize - writePos);
|
||||
System.arraycopy(data, offset, buf, writePos, l);
|
||||
writePos += l;
|
||||
if (writePos >= bufSize) writePos = 0;
|
||||
if (length > l) write(data, offset + l, length - l);
|
||||
} else {
|
||||
int l = Math.min(length, readPos - writePos - 1);
|
||||
System.arraycopy(data, offset, buf, writePos, l);
|
||||
writePos += l;
|
||||
if (writePos >= bufSize) writePos = 0;
|
||||
}
|
||||
|
||||
totalWritten += length;
|
||||
}
|
||||
}
|
||||
|
||||
public int remainingForRead() {
|
||||
if (writePos < readPos) return bufSize - (readPos - writePos);
|
||||
if (writePos == readPos) return 0;
|
||||
return writePos - readPos;
|
||||
}
|
||||
|
||||
public int skip(int amount){
|
||||
if (amount <= 0) return 0;
|
||||
int dataLen = 0;
|
||||
|
||||
synchronized (lock){
|
||||
if (remainingForRead() <= 0)
|
||||
return 0;
|
||||
|
||||
amount = Math.min(amount, remainingForRead());
|
||||
|
||||
// copy data
|
||||
if (readPos < writePos) {
|
||||
int l = Math.min(amount, writePos - readPos);
|
||||
readPos += l;
|
||||
if (readPos >= bufSize) readPos = 0;
|
||||
dataLen = l;
|
||||
} else {
|
||||
int l = Math.min(amount, bufSize - readPos);
|
||||
readPos += l;
|
||||
if (readPos >= bufSize) readPos = 0;
|
||||
dataLen = l;
|
||||
if (amount > l) dataLen += skip(amount - l);
|
||||
}
|
||||
lock.notifyAll();
|
||||
}
|
||||
|
||||
totalRead += dataLen;
|
||||
return dataLen;
|
||||
}
|
||||
|
||||
public int read(byte[] data, int offset, int len) {
|
||||
if (len == 0) return 0;
|
||||
int dataLen = 0;
|
||||
|
||||
synchronized (lock) {
|
||||
// see if we have enough data
|
||||
if (remainingForRead() <= 0){
|
||||
System.out.println("Warning: Audio starved. Not enough data.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = Math.min(len, remainingForRead());
|
||||
|
||||
// copy data
|
||||
if (readPos < writePos) {
|
||||
int l = Math.min(len, writePos - readPos);
|
||||
System.arraycopy(buf, readPos, data, offset, l);
|
||||
readPos += l;
|
||||
if (readPos >= bufSize) readPos = 0;
|
||||
dataLen = l;
|
||||
} else {
|
||||
int l = Math.min(len, bufSize - readPos);
|
||||
System.arraycopy(buf, readPos, data, offset, l);
|
||||
readPos += l;
|
||||
if (readPos >= bufSize) readPos = 0;
|
||||
dataLen = l;
|
||||
if (len > l) dataLen += read(data, offset + l, len - l);
|
||||
}
|
||||
lock.notifyAll();
|
||||
}
|
||||
|
||||
totalRead += dataLen;
|
||||
return dataLen;
|
||||
}
|
||||
|
||||
public long getTotalRead(){
|
||||
return totalRead;
|
||||
}
|
||||
|
||||
public long getTotalWritten(){
|
||||
return totalWritten;
|
||||
}
|
||||
|
||||
// public boolean isEOF() {
|
||||
// return eof;
|
||||
// }
|
||||
//
|
||||
// public void setEOF(boolean eof) {
|
||||
// this.eof = eof;
|
||||
// }
|
||||
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2010 jMonkeyEngine
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.jme3.video;
|
||||
|
||||
@Deprecated
|
||||
public class SystemClock implements Clock {
|
||||
|
||||
private long startTime = 0;
|
||||
|
||||
public SystemClock(){
|
||||
}
|
||||
|
||||
public boolean needReset(){
|
||||
return startTime == 0;
|
||||
}
|
||||
|
||||
public void reset(){
|
||||
startTime = System.nanoTime();
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return System.nanoTime() - startTime;
|
||||
}
|
||||
|
||||
public double getTimeSeconds(){
|
||||
return (double) getTime() / Clock.SECONDS_TO_NANOS;
|
||||
}
|
||||
|
||||
}
|
@ -1,203 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2010 jMonkeyEngine
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.jme3.video;
|
||||
|
||||
import com.jme3.app.SimpleApplication;
|
||||
import com.jme3.audio.AudioNode;
|
||||
import com.jme3.system.AppSettings;
|
||||
import com.jme3.texture.Image;
|
||||
import com.jme3.ui.Picture;
|
||||
import com.jme3.video.plugins.jheora.AVThread;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
|
||||
@Deprecated
|
||||
public class TestVideoPlayer extends SimpleApplication {
|
||||
|
||||
private Picture picture;
|
||||
private AVThread decoder;
|
||||
private Thread videoThread;
|
||||
private VQueue videoQueue;
|
||||
|
||||
private long lastFrameTime = 0;
|
||||
private Clock masterClock;
|
||||
private AudioNode source;
|
||||
|
||||
private float waitTime = 0;
|
||||
private VFrame frameToDraw = null;
|
||||
|
||||
public static void main(String[] args){
|
||||
TestVideoPlayer app = new TestVideoPlayer();
|
||||
AppSettings settings = new AppSettings(true);
|
||||
settings.setFrameRate(60);
|
||||
app.setSettings(settings);
|
||||
app.start();
|
||||
}
|
||||
|
||||
private void createVideo(){
|
||||
try {
|
||||
// uncomment to play video from harddrive
|
||||
// FileInputStream fis = new FileInputStream("E:\\bunny.ogg");
|
||||
InputStream fis = new URL("http://mirrorblender.top-ix.org/peach/bigbuckbunny_movies/big_buck_bunny_480p_stereo.ogg").openStream();
|
||||
|
||||
// increasing queued frames value from 5 will make web streamed
|
||||
// playback smoother at the cost of memory.
|
||||
videoQueue = new VQueue(5);
|
||||
decoder = new AVThread(fis, videoQueue);
|
||||
videoThread = new Thread(decoder, "Jheora Video Decoder");
|
||||
videoThread.setDaemon(true);
|
||||
videoThread.start();
|
||||
masterClock = decoder.getMasterClock();
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void simpleInitApp() {
|
||||
picture = new Picture("VideoPicture", true);
|
||||
picture.setPosition(0, 0);
|
||||
picture.setWidth(settings.getWidth());
|
||||
picture.setHeight(settings.getHeight());
|
||||
picture.setImage(assetManager, "Interface/Logo/Monkey.jpg", false);
|
||||
|
||||
// attach geometry to orthoNode
|
||||
rootNode.attachChild(picture);
|
||||
|
||||
// start video playback
|
||||
createVideo();
|
||||
}
|
||||
|
||||
private void drawFrame(VFrame frame){
|
||||
Image image = frame.getImage();
|
||||
frame.setImage(image);
|
||||
picture.setTexture(assetManager, frame, false);
|
||||
|
||||
// note: this forces renderer to upload frame immediately,
|
||||
// since it is going to be returned to the video queue pool
|
||||
// it could be used again.
|
||||
renderer.setTexture(0, frame);
|
||||
videoQueue.returnFrame(frame);
|
||||
lastFrameTime = frame.getTime();
|
||||
}
|
||||
|
||||
private void waitNanos(long time){
|
||||
long millis = (long) (time / Clock.MILLIS_TO_NANOS);
|
||||
int nanos = (int) (time - (millis * Clock.MILLIS_TO_NANOS));
|
||||
|
||||
try {
|
||||
Thread.sleep(millis, nanos);
|
||||
}catch (InterruptedException ex){
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void simpleUpdate(float tpf){
|
||||
if (source == null){
|
||||
if (decoder.getAudioStream() != null){
|
||||
source = new AudioNode(audioRenderer, decoder.getAudioStream(), null);
|
||||
source.setPositional(false);
|
||||
source.setReverbEnabled(false);
|
||||
audioRenderer.playSource(source);
|
||||
}else{
|
||||
// uncomment this statement to be able to play videos
|
||||
// without audio.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (waitTime > 0){
|
||||
waitTime -= tpf;
|
||||
if (waitTime > 0)
|
||||
return;
|
||||
else{
|
||||
waitTime = 0;
|
||||
drawFrame(frameToDraw);
|
||||
frameToDraw = null;
|
||||
}
|
||||
}else{
|
||||
VFrame frame;
|
||||
try {
|
||||
frame = videoQueue.take();
|
||||
} catch (InterruptedException ex){
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
if (frame.getTime() < lastFrameTime){
|
||||
videoQueue.returnFrame(frame);
|
||||
return;
|
||||
}
|
||||
|
||||
if (frame.getTime() == -2){
|
||||
// end of stream
|
||||
System.out.println("End of stream");
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
long AV_SYNC_THRESHOLD = 1 * Clock.MILLIS_TO_NANOS;
|
||||
|
||||
long delay = frame.getTime() - lastFrameTime;
|
||||
// delay -= tpf * Clock.SECONDS_TO_NANOS;
|
||||
long diff = frame.getTime() - masterClock.getTime();
|
||||
long syncThresh = delay > AV_SYNC_THRESHOLD ? delay : AV_SYNC_THRESHOLD;
|
||||
|
||||
// if difference is more than 1 second, synchronize.
|
||||
if (Math.abs(diff) < Clock.SECONDS_TO_NANOS){
|
||||
if(diff <= -syncThresh) {
|
||||
delay = 0;
|
||||
} else if(diff >= syncThresh) {
|
||||
delay = 2 * delay;
|
||||
}
|
||||
}
|
||||
// delay = diff;
|
||||
|
||||
System.out.println("M: "+decoder.getSystemClock().getTimeSeconds()+
|
||||
", V: "+decoder.getVideoClock().getTimeSeconds()+
|
||||
", A: "+decoder.getAudioClock().getTimeSeconds());
|
||||
|
||||
if (delay > 0){
|
||||
waitNanos(delay);
|
||||
drawFrame(frame);
|
||||
// waitTime = (float) ((double) delay / Clock.SECONDS_TO_NANOS);
|
||||
// frameToDraw = frame;
|
||||
}else{
|
||||
videoQueue.returnFrame(frame);
|
||||
lastFrameTime = frame.getTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2010 jMonkeyEngine
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.jme3.video;
|
||||
|
||||
import com.jme3.texture.Image.Format;
|
||||
import com.jme3.texture.Texture2D;
|
||||
import com.jme3.util.BufferUtils;
|
||||
|
||||
@Deprecated
|
||||
public class VFrame extends Texture2D {
|
||||
|
||||
private long time;
|
||||
|
||||
public VFrame(int width, int height){
|
||||
super(width, height, Format.RGBA8);
|
||||
getImage().setData(BufferUtils.createByteBuffer(width*height*4));
|
||||
}
|
||||
|
||||
public long getTime(){
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(long time){
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return super.toString() + "[Time="+time+"]";
|
||||
}
|
||||
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2010 jMonkeyEngine
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.jme3.video;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Deprecated
|
||||
public class VQueue extends ArrayBlockingQueue<VFrame> {
|
||||
|
||||
// private final ArrayList<VFrame> returnedFrames;
|
||||
private final ArrayBlockingQueue<VFrame> returnedFrames;
|
||||
|
||||
public VQueue(int bufferedFrames){
|
||||
super(bufferedFrames);
|
||||
// returnedFrames = new ArrayList<VFrame>(remainingCapacity());
|
||||
returnedFrames = new ArrayBlockingQueue<VFrame>(bufferedFrames * 3);
|
||||
}
|
||||
|
||||
public VFrame nextReturnedFrame(boolean waitForIt){
|
||||
// synchronized (returnedFrames){
|
||||
// while (returnedFrames.size() == 0){
|
||||
// if (!waitForIt)
|
||||
// return null;
|
||||
//
|
||||
// try {
|
||||
// returnedFrames.wait();
|
||||
// } catch (InterruptedException ex) {
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
try {
|
||||
return returnedFrames.take();
|
||||
} catch (InterruptedException ex) {
|
||||
ex.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void returnFrame(VFrame frame){
|
||||
returnedFrames.add(frame);
|
||||
|
||||
// synchronized (returnedFrames){
|
||||
// returnedFrames.add(frame);
|
||||
// returnedFrames.notifyAll();
|
||||
// }
|
||||
}
|
||||
}
|
@ -1,278 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2010 jMonkeyEngine
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.jme3.video.plugins.jheora;
|
||||
|
||||
import com.jcraft.jogg.Packet;
|
||||
import com.jcraft.jorbis.Block;
|
||||
import com.jcraft.jorbis.Comment;
|
||||
import com.jcraft.jorbis.DspState;
|
||||
import com.jcraft.jorbis.Info;
|
||||
import com.jme3.audio.AudioStream;
|
||||
import com.jme3.video.Clock;
|
||||
import com.jme3.video.RingBuffer;
|
||||
import com.jme3.video.SystemClock;
|
||||
import java.io.InputStream;
|
||||
|
||||
@Deprecated
|
||||
public class ADecoder extends InputStream implements Clock {
|
||||
|
||||
private int packetIndex = 0;
|
||||
|
||||
private final DspState dsp;
|
||||
private Block block;
|
||||
|
||||
private Info info;
|
||||
private Comment comment;
|
||||
|
||||
private float[][][] pcmAll = new float[1][][];
|
||||
private int[] index;
|
||||
|
||||
private AudioStream stream;
|
||||
private RingBuffer ringBuffer = new RingBuffer(48000 * 2 * 2 * 2);
|
||||
|
||||
private int UNCOMP_BUFSIZE = 4096;
|
||||
private byte[] uncompBuf = new byte[UNCOMP_BUFSIZE];
|
||||
|
||||
private long lastPts = 0;
|
||||
private long lastWritten = 0;
|
||||
private long lastRead = 0;
|
||||
private long lastPtsRead = 0;
|
||||
private long lastPtsWrite = 0;
|
||||
|
||||
private long timeDiffSum = 0;
|
||||
private int timesDesynced = 0;
|
||||
private Clock masterClock;
|
||||
|
||||
public ADecoder(){
|
||||
info = new Info();
|
||||
info.init();
|
||||
|
||||
comment = new Comment();
|
||||
comment.init();
|
||||
|
||||
dsp = new DspState();
|
||||
block = new Block(dsp);
|
||||
}
|
||||
|
||||
public void setMasterClock(Clock masterClock) {
|
||||
this.masterClock = masterClock;
|
||||
}
|
||||
|
||||
public AudioStream getAudioStream(){
|
||||
return stream;
|
||||
}
|
||||
|
||||
public long getTime(){
|
||||
long bytesRead = ringBuffer.getTotalRead();
|
||||
if (bytesRead == 0)
|
||||
return 0;
|
||||
|
||||
//long diff = bytesRead - lastWritten;
|
||||
long diff = bytesRead;
|
||||
long diffNs = (diff * Clock.SECONDS_TO_NANOS) / (2 * info.channels * info.rate);
|
||||
long timeSinceLastRead = System.nanoTime() - lastPtsRead;
|
||||
return /*lastPts +*/ diffNs + timeSinceLastRead;
|
||||
}
|
||||
|
||||
public double getTimeSeconds(){
|
||||
return (double) getTime() / Clock.SECONDS_TO_NANOS;
|
||||
}
|
||||
|
||||
public int read(){
|
||||
byte[] buf = new byte[1];
|
||||
int read = read(buf, 0, 1);
|
||||
if (read < 0)
|
||||
return -1;
|
||||
else
|
||||
return buf[0] & 0xff;
|
||||
}
|
||||
|
||||
private static final long NOSYNC_THRESH = 3 * Clock.SECONDS_TO_NANOS,
|
||||
AUDIO_DIFF_THRESH = Clock.SECONDS_TO_NANOS / 2;
|
||||
|
||||
private static final int NUM_DIFFS_FOR_SYNC = 5;
|
||||
private static final double PRODUCT_FOR_PREV = 6.0 / 10.0,
|
||||
PRODUCT_FOR_PREV_INV = 4.0 / 10.0;
|
||||
|
||||
private int needToSkip = 0;
|
||||
|
||||
/**
|
||||
* Only useful if audio is synced to something else.
|
||||
*/
|
||||
private void sync(){
|
||||
if (needToSkip > 0){
|
||||
int skipped = ringBuffer.skip(needToSkip);
|
||||
System.out.println("Skipped: "+skipped);
|
||||
needToSkip -= skipped;
|
||||
}
|
||||
|
||||
long masterTime = masterClock.getTime();
|
||||
long audioTime = getTime();
|
||||
long diff = audioTime - masterTime;
|
||||
if (diff < NOSYNC_THRESH){
|
||||
timeDiffSum = diff + (long) (timeDiffSum * PRODUCT_FOR_PREV);
|
||||
if (timesDesynced < NUM_DIFFS_FOR_SYNC){
|
||||
timesDesynced ++;
|
||||
}else{
|
||||
long avgDiff = (long) (timeDiffSum * PRODUCT_FOR_PREV_INV);
|
||||
if (Math.abs(avgDiff) >= AUDIO_DIFF_THRESH){
|
||||
if (diff < 0){
|
||||
int toSkip = (int) ((-diff * 2 * info.channels * info.rate) / Clock.SECONDS_TO_NANOS);
|
||||
int skipped = ringBuffer.skip(toSkip);
|
||||
System.out.println("Skipped: "+skipped);
|
||||
if (skipped < toSkip)
|
||||
needToSkip = toSkip - skipped;
|
||||
|
||||
timeDiffSum = 0;
|
||||
timesDesynced = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
timesDesynced = 0;
|
||||
timeDiffSum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] buf, int offset, int length){
|
||||
// int diff = (int) (ringBuffer.getTotalWritten() - ringBuffer.getTotalRead());
|
||||
// if ( diff > info.rate * info.channels * 2){
|
||||
// System.out.println("Warning: more than 1 second lag for audio. Adjusting..");
|
||||
// ringBuffer.skip( diff );
|
||||
// }
|
||||
|
||||
|
||||
// if (masterClock != null)
|
||||
// sync();
|
||||
|
||||
int r = ringBuffer.read(buf, offset, length);
|
||||
if (r <= 0){
|
||||
// // put silence
|
||||
for (int i = 0; i < length; i++){
|
||||
buf[offset + i] = 0x0;
|
||||
}
|
||||
return length;
|
||||
}else{
|
||||
lastPtsRead = System.nanoTime();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
public void decodeDsp(Packet packet){
|
||||
if (block.synthesis(packet) == 0) {
|
||||
dsp.synthesis_blockin(block);
|
||||
}
|
||||
|
||||
int samplesAvail;
|
||||
int channels = info.channels;
|
||||
while ((samplesAvail = dsp.synthesis_pcmout(pcmAll, index)) > 0) {
|
||||
float[][] pcm = pcmAll[0];
|
||||
int samplesCanRead = UNCOMP_BUFSIZE / (channels*2);
|
||||
int samplesToRead = (samplesAvail < samplesCanRead ? samplesAvail : samplesCanRead);
|
||||
|
||||
// convert floats to 16 bit signed ints and interleave
|
||||
for (int i = 0; i < channels; i++) {
|
||||
// each sample is two bytes, the sample for the 2nd
|
||||
// channel is at index 2, etc.
|
||||
int writeOff = i * 2;
|
||||
int readOff = index[i];
|
||||
for (int j = 0; j < samplesToRead; j++) {
|
||||
int val = (int) (pcm[i][readOff + j] * 32767.0);
|
||||
// guard against clipping
|
||||
if (val > 32767) {
|
||||
val = 32767;
|
||||
}if (val < -32768) {
|
||||
val = -32768;
|
||||
}
|
||||
uncompBuf[writeOff] = (byte) (val);
|
||||
uncompBuf[writeOff + 1] = (byte) (val >> 8);
|
||||
|
||||
writeOff += 2 * channels; // each sample is 2 bytes
|
||||
}
|
||||
}
|
||||
|
||||
ringBuffer.write(uncompBuf, 0, samplesToRead * channels * 2);
|
||||
|
||||
// tell vorbis how many samples were actualy consumed
|
||||
dsp.synthesis_read(samplesToRead);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(){
|
||||
}
|
||||
|
||||
public void decode(Packet packet){
|
||||
if (packetIndex < 3) {
|
||||
if (info.synthesis_headerin(comment, packet) < 0) {
|
||||
// error case; not a Vorbis header
|
||||
System.err.println("does not contain Vorbis audio data.");
|
||||
return;
|
||||
}
|
||||
if (packetIndex == 2) {
|
||||
dsp.synthesis_init(info);
|
||||
block.init(dsp);
|
||||
System.out.println("vorbis: "+info);
|
||||
System.out.println(comment.toString());
|
||||
index = new int[info.channels];
|
||||
|
||||
if (stream == null){
|
||||
stream = new AudioStream();
|
||||
stream.setupFormat(info.channels, 16, info.rate);
|
||||
stream.updateData(this, -1);
|
||||
}
|
||||
|
||||
if (masterClock instanceof SystemClock){
|
||||
SystemClock clock = (SystemClock) masterClock;
|
||||
if (clock.needReset()){
|
||||
clock.reset();
|
||||
System.out.println("Note: master clock was reset by audio");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
long gp = packet.granulepos;
|
||||
if (gp != -1){
|
||||
lastPts = (gp * Clock.SECONDS_TO_NANOS) / info.rate;
|
||||
lastWritten = ringBuffer.getTotalWritten();
|
||||
lastRead = ringBuffer.getTotalRead();
|
||||
lastPtsWrite = System.nanoTime();
|
||||
}
|
||||
|
||||
decodeDsp(packet);
|
||||
}
|
||||
packetIndex++;
|
||||
}
|
||||
|
||||
}
|
@ -1,223 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2010 jMonkeyEngine
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.jme3.video.plugins.jheora;
|
||||
|
||||
import com.jcraft.jogg.Packet;
|
||||
import com.jcraft.jogg.Page;
|
||||
import com.jcraft.jogg.StreamState;
|
||||
import com.jcraft.jogg.SyncState;
|
||||
import com.jme3.audio.AudioStream;
|
||||
import com.jme3.util.IntMap;
|
||||
import com.jme3.video.Clock;
|
||||
import com.jme3.video.SystemClock;
|
||||
import com.jme3.video.VQueue;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Deprecated
|
||||
public class AVThread implements Runnable {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(AVThread.class.getName());
|
||||
|
||||
private static final int BUFFSIZE = 8192;
|
||||
|
||||
/**
|
||||
* OggPage.
|
||||
*/
|
||||
private Page page;
|
||||
|
||||
/**
|
||||
* OggPacket, constructed from OggPages.
|
||||
*/
|
||||
private Packet packet;
|
||||
|
||||
/**
|
||||
* SyncState.
|
||||
*/
|
||||
private SyncState syncState;
|
||||
|
||||
/**
|
||||
* Stream of .ogg file.
|
||||
*/
|
||||
private InputStream oggStream;
|
||||
|
||||
private AtomicBoolean cancel = new AtomicBoolean(false);
|
||||
|
||||
private IntMap<StreamState> streams = new IntMap<StreamState>();
|
||||
private int theoraSerial, vorbisSerial;
|
||||
private ADecoder audioDecoder;
|
||||
private VDecoder videoDecoder;
|
||||
private Clock masterClock;
|
||||
private Clock systemClock;
|
||||
|
||||
public AVThread(InputStream oggStream, VQueue videoQueue){
|
||||
this.oggStream = oggStream;
|
||||
videoDecoder = new VDecoder(videoQueue);
|
||||
audioDecoder = new ADecoder();
|
||||
systemClock = new SystemClock();
|
||||
// masterClock = systemClock;//audioDecoder;
|
||||
masterClock = audioDecoder;
|
||||
audioDecoder.setMasterClock(masterClock);
|
||||
videoDecoder.setMasterClock(masterClock);
|
||||
// masterClock = videoDecoder;
|
||||
// masterClock = systemClock;
|
||||
// audioDecoder.setMasterClock(masterClock);
|
||||
}
|
||||
|
||||
public AudioStream getAudioStream(){
|
||||
return audioDecoder.getAudioStream();
|
||||
}
|
||||
|
||||
public void stop(){
|
||||
cancel.set(true);
|
||||
}
|
||||
|
||||
private void done(){
|
||||
videoDecoder.close();
|
||||
audioDecoder.close();
|
||||
try {
|
||||
oggStream.close();
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.SEVERE, "Error while closing Ogg Video", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Clock getMasterClock(){
|
||||
return masterClock;
|
||||
}
|
||||
|
||||
public Clock getSystemClock(){
|
||||
return systemClock;
|
||||
}
|
||||
|
||||
public Clock getVideoClock(){
|
||||
return videoDecoder;
|
||||
}
|
||||
|
||||
public Clock getAudioClock(){
|
||||
return audioDecoder;
|
||||
}
|
||||
|
||||
public void run(){
|
||||
page = new Page();
|
||||
packet = new Packet();
|
||||
syncState = new SyncState();
|
||||
|
||||
while (!cancel.get()) {
|
||||
int index = syncState.buffer(BUFFSIZE);
|
||||
|
||||
// Read from stream into syncState's buffer.
|
||||
int read;
|
||||
try {
|
||||
read = oggStream.read(syncState.data, index, BUFFSIZE);
|
||||
} catch (IOException ex){
|
||||
logger.log(Level.SEVERE, "Error while decoding Ogg Video", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
if (read < 0){
|
||||
// EOF
|
||||
break;
|
||||
}
|
||||
|
||||
syncState.wrote(read);
|
||||
|
||||
while (!cancel.get()) {
|
||||
// Acquire page from syncState
|
||||
int res = syncState.pageout(page);
|
||||
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 = page.serialno();
|
||||
StreamState state = streams.get(serial);
|
||||
boolean newStream = false;
|
||||
if (state == null){
|
||||
state = new StreamState();
|
||||
state.init(serial);
|
||||
state.reset();
|
||||
streams.put(serial, state);
|
||||
newStream = true;
|
||||
}
|
||||
|
||||
// Give StreamState the page
|
||||
res = state.pagein(page);
|
||||
if (res < 0) {
|
||||
// error; stream version mismatch perhaps
|
||||
System.err.println("Error reading first page of Ogg bitstream data.");
|
||||
return;
|
||||
}
|
||||
while (!cancel.get()) {
|
||||
// Get a packet out of the stream state
|
||||
res = state.packetout(packet);
|
||||
if (res == 0)
|
||||
break;
|
||||
|
||||
if (res == -1) {
|
||||
// missing or corrupt data at this page position
|
||||
// no reason to complain; already complained above
|
||||
} else {
|
||||
// Packet acquired!
|
||||
if (newStream) {
|
||||
// typefind
|
||||
int packetId = packet.packet;
|
||||
byte[] packetBase = packet.packet_base;
|
||||
if (packetBase[packetId + 1] == 0x76) {
|
||||
vorbisSerial = serial;
|
||||
} else if (packet.packet_base[packet.packet + 1] == 0x73) {
|
||||
// smoke video! ignored
|
||||
logger.log(Level.WARNING, "Smoke video detected. Unsupported!");
|
||||
} else if (packet.packet_base[packet.packet + 1] == 0x74) {
|
||||
theoraSerial = serial;
|
||||
}
|
||||
}
|
||||
if (serial == theoraSerial){
|
||||
videoDecoder.decode(packet);
|
||||
}else if (serial == vorbisSerial){
|
||||
audioDecoder.decode(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
done();
|
||||
}
|
||||
|
||||
}
|
@ -1,184 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2010 jMonkeyEngine
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.jme3.video.plugins.jheora;
|
||||
|
||||
import com.fluendo.jheora.Comment;
|
||||
import com.fluendo.jheora.Info;
|
||||
import com.fluendo.jheora.State;
|
||||
import com.fluendo.jheora.YUVBuffer;
|
||||
import com.jcraft.jogg.Packet;
|
||||
import com.jme3.video.Clock;
|
||||
import com.jme3.video.SystemClock;
|
||||
import com.jme3.video.VFrame;
|
||||
import com.jme3.video.VQueue;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@Deprecated
|
||||
public class VDecoder implements Clock {
|
||||
|
||||
private int packetIndex = 0;
|
||||
|
||||
private Info info;
|
||||
private Comment comment;
|
||||
|
||||
private State state;
|
||||
private YUVBuffer yuv;
|
||||
|
||||
private int xOff, yOff, width, height;
|
||||
private YUVConv conv = new YUVConv();
|
||||
|
||||
private VQueue videoQueue;
|
||||
|
||||
private long lastTs = -1;
|
||||
private long lastUpdateTime = 0;
|
||||
private Clock masterClock;
|
||||
|
||||
public VDecoder(VQueue queue) {
|
||||
info = new Info();
|
||||
comment = new Comment();
|
||||
state = new State();
|
||||
yuv = new YUVBuffer();
|
||||
videoQueue = queue;
|
||||
}
|
||||
|
||||
public void setMasterClock(Clock masterClock) {
|
||||
this.masterClock = masterClock;
|
||||
}
|
||||
|
||||
public long getTime(){
|
||||
if (lastTs == -1)
|
||||
return 0;
|
||||
|
||||
long timeDiff = System.nanoTime() - lastUpdateTime;
|
||||
return lastTs + timeDiff;
|
||||
}
|
||||
|
||||
public double getTimeSeconds(){
|
||||
return (double) getTime() / Clock.SECONDS_TO_NANOS;
|
||||
}
|
||||
|
||||
private void initializeFrames(){
|
||||
for (int i = 0; i < videoQueue.remainingCapacity(); i++){
|
||||
videoQueue.returnFrame(new VFrame(width, height));
|
||||
}
|
||||
}
|
||||
|
||||
private void decodeRgbFromBuffer(long time){
|
||||
VFrame frame = videoQueue.nextReturnedFrame(true);
|
||||
conv.convert(yuv, xOff, yOff, width, height);
|
||||
int[] rgb = conv.getRGBData();
|
||||
|
||||
frame.setTime(time);
|
||||
ByteBuffer data = frame.getImage().getData(0);
|
||||
data.clear();
|
||||
data.asIntBuffer().put(rgb);
|
||||
|
||||
try {
|
||||
// if it throws an exception someone
|
||||
// else modified it. "unknown error"..
|
||||
videoQueue.put(frame);
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
public void close(){
|
||||
// enqueue a frame with time == -2 to indicate end of stream
|
||||
VFrame frame = videoQueue.nextReturnedFrame(true);
|
||||
frame.setTime(-2);
|
||||
try {
|
||||
videoQueue.put(frame);
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
public void decode(Packet packet) {
|
||||
//System.out.println ("creating packet");
|
||||
if (packetIndex < 3) {
|
||||
//System.out.println ("decoding header");
|
||||
if (info.decodeHeader(comment, packet) < 0) {
|
||||
// error case; not a theora header
|
||||
System.err.println("does not contain Theora video data.");
|
||||
return;
|
||||
}
|
||||
if (packetIndex == 2) {
|
||||
state.decodeInit(info);
|
||||
|
||||
System.out.println("theora frame: " + info.frame_width + "x" + info.frame_height);
|
||||
System.out.println("theora resolution: " + info.width + "x" + info.height);
|
||||
System.out.println("theora aspect: " + info.aspect_numerator + "x" + info.aspect_denominator);
|
||||
System.out.println("theora framerate: " + info.fps_numerator + "x" + info.fps_denominator);
|
||||
|
||||
xOff = info.offset_x;
|
||||
yOff = info.offset_y;
|
||||
width = info.frame_width;
|
||||
height = info.frame_height;
|
||||
initializeFrames();
|
||||
|
||||
if (masterClock instanceof SystemClock){
|
||||
SystemClock clock = (SystemClock) masterClock;
|
||||
if (clock.needReset()){
|
||||
clock.reset();
|
||||
System.out.println("Note: master clock was reset by video");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// convert to nanos
|
||||
long granulePos = packet.granulepos;
|
||||
long time = (long) (state.granuleTime(granulePos) * Clock.SECONDS_TO_NANOS);
|
||||
long oneFrameTime = (long) ((Clock.SECONDS_TO_NANOS * info.fps_denominator) / info.fps_numerator);
|
||||
if (time >= 0){
|
||||
lastTs = time;
|
||||
}else{
|
||||
lastTs += oneFrameTime;
|
||||
time = lastTs;
|
||||
}
|
||||
lastUpdateTime = System.nanoTime();
|
||||
|
||||
if (state.decodePacketin(packet) != 0) {
|
||||
System.err.println("Error Decoding Theora.");
|
||||
return;
|
||||
}
|
||||
|
||||
// if (time >= 0){
|
||||
if (state.decodeYUVout(yuv) != 0) {
|
||||
System.err.println("Error getting the picture.");
|
||||
return;
|
||||
}
|
||||
decodeRgbFromBuffer( time );
|
||||
// }
|
||||
}
|
||||
packetIndex++;
|
||||
}
|
||||
|
||||
}
|
@ -1,143 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2010 jMonkeyEngine
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.jme3.video.plugins.jheora;
|
||||
|
||||
import com.fluendo.jheora.YUVBuffer;
|
||||
|
||||
@Deprecated
|
||||
public final class YUVConv {
|
||||
|
||||
private int[] pixels;
|
||||
|
||||
private static final int VAL_RANGE = 256;
|
||||
private static final int SHIFT = 16;
|
||||
|
||||
private static final int CR_FAC = (int) (1.402 * (1 << SHIFT));
|
||||
private static final int CB_FAC = (int) (1.772 * (1 << SHIFT));
|
||||
private static final int CR_DIFF_FAC = (int) (0.71414 * (1 << SHIFT));
|
||||
private static final int CB_DIFF_FAC = (int) (0.34414 * (1 << SHIFT));
|
||||
|
||||
private static int[] r_tab = new int[VAL_RANGE * 3];
|
||||
private static int[] g_tab = new int[VAL_RANGE * 3];
|
||||
private static int[] b_tab = new int[VAL_RANGE * 3];
|
||||
|
||||
static {
|
||||
setupRgbYuvAccelerators();
|
||||
}
|
||||
|
||||
private static final short clamp255(int val) {
|
||||
val -= 255;
|
||||
val = -(255 + ((val >> (31)) & val));
|
||||
return (short) -((val >> 31) & val);
|
||||
}
|
||||
|
||||
private static void setupRgbYuvAccelerators() {
|
||||
for (int i = 0; i < VAL_RANGE * 3; i++) {
|
||||
r_tab[i] = clamp255(i - VAL_RANGE);
|
||||
g_tab[i] = clamp255(i - VAL_RANGE) << 8;
|
||||
b_tab[i] = clamp255(i - VAL_RANGE) << 16;
|
||||
}
|
||||
}
|
||||
|
||||
public YUVConv(){
|
||||
}
|
||||
|
||||
public int[] getRGBData(){
|
||||
return pixels;
|
||||
}
|
||||
|
||||
public void convert(YUVBuffer yuv, int xOff, int yOff, int width, int height) {
|
||||
if (pixels == null){
|
||||
pixels = new int[width*height];
|
||||
}
|
||||
// Set up starting values for YUV pointers
|
||||
int YPtr = yuv.y_offset + xOff + yOff * (yuv.y_stride);
|
||||
int YPtr2 = YPtr + yuv.y_stride;
|
||||
int UPtr = yuv.u_offset + xOff/2 + (yOff/2)*(yuv.uv_stride);
|
||||
int VPtr = yuv.v_offset + xOff/2 + (yOff/2)*(yuv.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 = yuv.y_stride * 2 - (width2) * 2;
|
||||
int UVStep = yuv.uv_stride - (width2);
|
||||
int RGBStep = width;
|
||||
|
||||
for (int i = 0; i < height2; i++) {
|
||||
for (int j = 0; j < width2; j++) {
|
||||
// groups of four pixels
|
||||
int UFactor = yuv.data[UPtr++] - 128;
|
||||
int VFactor = yuv.data[VPtr++] - 128;
|
||||
int GFactor = UFactor * CR_DIFF_FAC + VFactor * CB_DIFF_FAC - (VAL_RANGE<<SHIFT);
|
||||
|
||||
UFactor = UFactor * CR_FAC + (VAL_RANGE<<SHIFT);
|
||||
VFactor = VFactor * CB_FAC + (VAL_RANGE<<SHIFT);
|
||||
|
||||
int YVal = yuv.data[YPtr] << SHIFT;
|
||||
pixels[RGBPtr] = r_tab[(YVal + VFactor)>>SHIFT] |
|
||||
b_tab[(YVal + UFactor)>>SHIFT] |
|
||||
g_tab[(YVal - GFactor)>>SHIFT];
|
||||
|
||||
YVal = yuv.data[YPtr+1] << SHIFT;
|
||||
pixels[RGBPtr+1] = r_tab[(YVal + VFactor)>>SHIFT] |
|
||||
b_tab[(YVal + UFactor)>>SHIFT] |
|
||||
g_tab[(YVal - GFactor)>>SHIFT];
|
||||
|
||||
YVal = yuv.data[YPtr2] << SHIFT;
|
||||
pixels[RGBPtr2] = r_tab[(YVal + VFactor)>>SHIFT] |
|
||||
b_tab[(YVal + UFactor)>>SHIFT] |
|
||||
g_tab[(YVal - GFactor)>>SHIFT];
|
||||
|
||||
YVal = yuv.data[YPtr2+1] << SHIFT;
|
||||
pixels[RGBPtr2+1] = r_tab[(YVal + VFactor)>>SHIFT] |
|
||||
b_tab[(YVal + UFactor)>>SHIFT] |
|
||||
g_tab[(YVal - GFactor)>>SHIFT];
|
||||
|
||||
YPtr += 2;
|
||||
YPtr2 += 2;
|
||||
RGBPtr += 2;
|
||||
RGBPtr2 += 2;
|
||||
}
|
||||
|
||||
// Increment the various pointers
|
||||
YPtr += YStep;
|
||||
YPtr2 += YStep;
|
||||
UPtr += UVStep;
|
||||
VPtr += UVStep;
|
||||
RGBPtr += RGBStep;
|
||||
RGBPtr2 += RGBStep;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user