00001 package org.hfbk.vid; 00002 00003 import java.nio.ByteBuffer; 00004 00005 import net.sf.ffmpeg_java.AVCodecLibrary; 00006 import net.sf.ffmpeg_java.AVCodecLibrary.AVCodecContext; 00007 import net.sf.ffmpeg_java.AVFormatLibrary.AVPacket; 00008 00009 import org.dronus.al.ALAudioThread; 00010 import org.hfbk.vis.Prefs; 00011 00012 import com.sun.jna.Pointer; 00013 import com.sun.jna.ptr.IntByReference; 00014 00022 public class AVAudioThread extends AVStreamThread { 00023 00024 final static int AUDIO_BUFFER=0xFFFF; 00025 // our OpenAl audio engine 00026 // it is NOT started as a thread on its own, 00027 // but run from this one! 00028 ALAudioThread alThread; 00029 00030 final int SAMPLES=AVCodecLibrary.AVCODEC_MAX_AUDIO_FRAME_SIZE; 00031 Pointer decoded; 00032 00033 int time; 00034 00036 public AVAudioThread(AVCodecContext ctx) { 00037 super("AVAudioThread", ctx,AUDIO_BUFFER); 00038 00039 setPriority(Thread.MAX_PRIORITY-1); 00040 00041 int s=ctx.sample_rate; 00042 int b=ctx.bits_per_coded_sample; 00043 int c=ctx.channels; 00044 if (b==0) b=16; 00045 00046 alThread=new ALAudioThread(s, b, c){ 00047 protected ByteBuffer poll(){ 00048 AVPacket p=AVAudioThread.this.poll(); 00049 if(p!=null){ 00050 tick((int)p.pts); 00051 return decodeAudio(p); 00052 } 00053 // if the stream is finished 00054 // and the queue already used up 00055 else if (AVAudioThread.this.finished) 00056 running=false; 00057 00058 return null; 00059 } 00060 00061 public void tick(int time) { 00062 AVAudioThread.this.tick(time); 00063 AVAudioThread.this.time=time; 00064 } 00065 }; 00066 00067 synchronized(AV.UTIL){ 00068 decoded=AV.UTIL.av_malloc(SAMPLES); 00069 } 00070 } 00071 00072 void setPlaying(boolean playing){ 00073 super.setPlaying(playing); 00074 alThread.playing=playing; 00075 }; 00076 00077 public void run() { 00078 alThread.run(); 00079 close(); 00080 } 00081 00082 void setRunning(boolean running) { 00083 super.setRunning(running); 00084 alThread.running=running; 00085 } 00086 00087 protected void close(){ 00088 if(Prefs.current.debug) System.out.println("AVAudio finished."); 00089 super.close(); 00090 synchronized(AV.UTIL){ 00091 AV.UTIL.av_free(decoded); 00092 } 00093 if(Prefs.current.debug) System.out.println("AVAudio down!"); 00094 } 00095 00096 /* decode one audio AVPacket */ 00097 ByteBuffer decodeAudio(AVPacket packet){ 00098 final IntByReference bufferSize = new IntByReference(SAMPLES); 00099 00100 AV.CODEC.avcodec_decode_audio2(ctx, decoded, 00101 bufferSize, packet.data, packet.size); 00102 free(packet); 00103 00104 return decoded.getByteBuffer(0, bufferSize.getValue()); 00105 } 00106 }