2011-02-19 134 views

回答

1

JMF是基本上

您可以使用xuggler在Java秋千玩WMV文件。

Xuggler is a free open-source library for Java developers to uncompress, manipulate, and compress recorded or live video

You can view the code here

package com.xuggle.xuggler.demos; 
import com.xuggle.xuggler.demos.VideoImage; 
import javax.sound.sampled.AudioFormat; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.DataLine; 
import javax.sound.sampled.LineUnavailableException; 
import javax.sound.sampled.SourceDataLine; 

import com.xuggle.xuggler.IAudioSamples; 
import com.xuggle.xuggler.IContainer; 
import com.xuggle.xuggler.IPacket; 
import com.xuggle.xuggler.IStream; 
import com.xuggle.xuggler.IStreamCoder; 
import com.xuggle.xuggler.ICodec; 


public class DecodeAndPlayAudio 
{ 
    private static SourceDataLine mLine; 

/** 
    * Takes a media container (file) as the first argument, opens it, 
    * opens up the default audio device on your system, and plays back the audio. 
    * 
    * @param args Must contain one string which represents a filename 
    */ 
public static void main(String[] args) 
{ 
    if (args.length <= 0) 
    throw new IllegalArgumentException("must pass in a filename as the first argument"); 

String filename = args[0]; 

// Create a Xuggler container object 
IContainer container = IContainer.make(); 

// Open up the container 
if (container.open(filename, IContainer.Type.READ, null) < 0) 
    throw new IllegalArgumentException("could not open file: " + filename); 

// query how many streams the call to open found 
int numStreams = container.getNumStreams(); 

// and iterate through the streams to find the first audio stream 
int audioStreamId = -1; 
IStreamCoder audioCoder = null; 
for(int i = 0; i < numStreams; i++) 
{ 
    // Find the stream object 
    IStream stream = container.getStream(i); 
    // Get the pre-configured decoder that can decode this stream; 
    IStreamCoder coder = stream.getStreamCoder(); 

    if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_AUDIO) 
    { 
    audioStreamId = i; 
    audioCoder = coder; 
    break; 
    } 
} 
if (audioStreamId == -1) 
    throw new RuntimeException("could not find audio stream in container: "+filename); 

/* 
* Now we have found the audio stream in this file. Let's open up our decoder so it can 
* do work. 
*/ 
if (audioCoder.open() < 0) 
    throw new RuntimeException("could not open audio decoder for container: "+filename); 

/* 
* And once we have that, we ask the Java Sound System to get itself ready. 
*/ 
openJavaSound(audioCoder); 

/* 
* Now, we start walking through the container looking at each packet. 
*/ 
IPacket packet = IPacket.make(); 
while(container.readNextPacket(packet) >= 0) 
{ 
    /* 
    * Now we have a packet, let's see if it belongs to our audio stream 
    */ 
    if (packet.getStreamIndex() == audioStreamId) 
    { 
    /* 
    * 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, audioCoder.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 < packet.getSize()) 
    { 
     int bytesDecoded = audioCoder.decodeAudio(samples, packet, offset); 
     if (bytesDecoded < 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()) 
     { 
     playJavaSound(samples); 
     } 
    } 
    } 
    else 
    { 
    /* 
    * This packet isn't part of our audio stream, so we just silently drop it. 
    */ 
    do {} while(false); 
    } 

} 
/* 
* Technically since we're exiting anyway, these will be cleaned up by 
* the garbage collector... but because we're nice people and want 
* to be invited places for Christmas, we're going to show how to clean up. 
*/ 
closeJavaSound(); 

if (audioCoder != null) 
{ 
    audioCoder.close(); 
    audioCoder = null; 
} 
if (container !=null) 
{ 
    container.close(); 
    container = null; 
} 
} 

private static void openJavaSound(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 
{ 
    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"); 
} 

}

private static void playJavaSound(IAudioSamples aSamples) 
{ 
/** 
* We're just going to dump all the samples into the line. 
*/ 
byte[] rawBytes = aSamples.getData().getByteArray(0, aSamples.getSize()); 
mLine.write(rawBytes, 0, aSamples.getSize()); 
} 

private static void closeJavaSound() 
{ 
if (mLine != null) 
{ 
    /* 
    * Wait for the line to finish playing 
    */ 
    mLine.drain(); 
    /* 
    * Close the line. 
    */ 
    mLine.close(); 
    mLine=null; 
    } 
} 
}