Note that there are some explanatory texts on larger screens.

plurals
  1. POSourceDataLine.start() nulls the object
    primarykey
    data
    text
    <p>Here's the code that has the symptoms:</p> <pre><code> /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package com.zove.xuggleraudio; import com.xuggle.xuggler.IAudioSamples; import com.xuggle.xuggler.IContainer; import com.xuggle.xuggler.IStream; import com.xuggle.xuggler.IStreamCoder; import com.xuggle.xuggler.ICodec; import com.xuggle.xuggler.IPacket; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; import javax.sound.sampled.Line; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; /** * Class that represents an audio player with the expected * controls (start, stop, pause, resume). * @author Mciavilli */ public class Audio { //The name of the file to be played private final String filename; //Our connection to the mixer private final SourceDataLine mLine; //The index of the audio stream inside the file private final int audioId; //Xuggler media container private final IContainer container; //The stream decoder private final IStreamCoder streamCoder; /* * Constructor that takes a String argument */ public Audio(String filename) { this.filename = filename; //Create Xuggler container object this.container = IContainer.make(); //Open the container if(container.open(filename, IContainer.Type.READ, null) &lt; 0) throw new IllegalArgumentException("Invalid file name: " + this.filename); //find the audio stream within contained streams this.audioId = getAudioId(container); //get the audio stream IStream stream = container.getStream(audioId); //get the stream decoder this.streamCoder = stream.getStreamCoder(); //open the stream decoder if (this.streamCoder.open() &lt; 0) throw new RuntimeException("could not open audio decoder for container: " + filename); //Get a pipe to the sound mixer this.mLine = readySoundSystem(streamCoder); } private int getAudioId(IContainer container) { //see how many streams are there int numStreams = container.getNumStreams(); int audioId = -1; for(int i = 0; i &lt; numStreams ; i++) { IStream stream = container.getStream(i); IStreamCoder streamCoder = stream.getStreamCoder(); if(streamCoder.getCodecType() == ICodec.Type.CODEC_TYPE_AUDIO) audioId = i; break; }//end for statement //No audio stream found if(audioId == -1) throw new RuntimeException("Failed to find an audio stream in:" + this.filename); return audioId; }//end method getAudioId private SourceDataLine readySoundSystem(IStreamCoder aAudioCoder) { AudioFormat audioFormat = new AudioFormat(aAudioCoder.getSampleRate(), (int)IAudioSamples.findSampleBitDepth(aAudioCoder.getSampleFormat()), aAudioCoder.getChannels(), true, /* xuggler defaults to signed 16 bit samples */ false); DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat); try { SourceDataLine mLine = (SourceDataLine) AudioSystem.getLine(info); /** * if that succeeded, try opening the line. */ mLine.open(audioFormat); /** * And if that succeed, start the line. */ mLine.start(); } catch (LineUnavailableException e) { throw new RuntimeException("could not open audio line"); } return mLine; }//end method readySoundSystem /* * starts playing the file. * returns true if successful. * should be called only once per Audio object */ public boolean start() { if(!mLine.isActive()) { IPacket packet = IPacket.make(); while(container.readNextPacket(packet) &gt;= 0) { /* * Now we have a packet, let's see if it belongs to our audio stream */ if (packet.getStreamIndex() == this.audioId) { /* * We allocate a set of samples with the same number of channels as the * coder tells us is in this buffer. * * We also pass in a buffer size (1024 in our example), although Xuggler * will probably allocate more space than just the 1024 (it's not important why). */ IAudioSamples samples = IAudioSamples.make(1024, this.streamCoder.getChannels()); /* * A packet can actually contain multiple sets of samples (or frames of samples * in audio-decoding speak). So, we may need to call decode audio multiple * times at different offsets in the packet's data. We capture that here. */ int offset = 0; /* * Keep going until we've processed all data */ while(offset &lt; packet.getSize()) { int bytesDecoded = this.streamCoder.decodeAudio(samples, packet, offset); if (bytesDecoded &lt; 0) throw new RuntimeException("got error decoding audio in: " + filename); offset += bytesDecoded; /* * Some decoder will consume data in a packet, but will not be able to construct * a full set of samples yet. Therefore you should always check if you * got a complete set of samples from the decoder */ if (samples.isComplete()) { playSound(samples); } }//end inner while block }//end inner if block else { /* * This packet isn't part of our audio stream, so we just silently drop it. */ do {} while(false); }//end else block }//end outer while block //success! return true; }//end outer if block //The sound is already playing return false; }//end method start private void playSound(IAudioSamples aSamples) { /** * We're just going to dump all the samples into the line. */ byte[] rawBytes = aSamples.getData().getByteArray(0, aSamples.getSize()); this.mLine.write(rawBytes, 0, aSamples.getSize()); }//end method playJavaSound /* * stops the playback * returns true if suucessful */ public boolean stop() { if(mLine.isActive()) { this.mLine.stop(); return true; } return false; } public static void main(String args[]) throws InterruptedException { if(args.length != 1) throw new IllegalArgumentException("illegal arguments passed"); Audio audio = new Audio(args[0]); audio.start(); Thread.sleep(10 * 1000); audio.stop(); } }//end class Audio </code></pre> <p>The line that causes the problem is line 104:</p> <pre><code>mLine.start(); </code></pre> <p>When i checked the debugger, the mLine object (a SourceDataLine object) is fine until this line is executed, which causes mLine to equal 'null'.</p> <p>I think this problem is the same as <a href="https://stackoverflow.com/questions/7396364/null-pointer-exception-while-writing-to-sourcedataline">here</a>.</p> <p>I also tried to use Clip instead of SourceDataLine which ended up having the same issue.</p> <p>What's interesting is that this problem doesn't happen in the <a href="http://xuggle.googlecode.com/svn/trunk/java/xuggle-xuggler/src/com/xuggle/xuggler/demos/DecodeAndPlayAudio.java" rel="nofollow noreferrer">original Xuggler program</a>, and calling start() didn't have that bad effect.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload