本文主要阐述JMF捕获音频和视频技术。并给出源代码实例。
author: ZJ
06-11-16
1. 捕获媒体数据的步骤:
l 查询CaptureDeviceManager,来定位你需要使用的媒体采集设备。
l 得到此设备的CaptureDeviceInfo实例。
l 从此CaptureDeviceInfo实例获得一个MediaLocator,并通过它来创建一个DataSource。
l 用此DataSource创建一个Player或Processor。
l 启动此Player或Processor开始捕获媒体数据。
2.CaptureDeviceManager、CaptureDeviceInfo、MediaLocator
在JMF中,CaptureDeviceManager也是一个manager类,它提供给了一个列表,这个列表显示当前系统可以被使用的设备名称。同时CaptureDeviceManager可以通过查询的方法对设备进行定位并返回设备的配置信息对象CaptureDeviceInfo,它也可以通过注册的方法向列表加入一个新的设备信息,以便为JMF使用。
设备可通过CaptureDeviceManager的getDevice()方法直接获得设备控制权,设备的控制权一旦得到,就可以以此设备作为一个MediaLocator,可以通过CaptureDeviceInfo的getLocator()方法得到。
3. JMF识别的音频采集设备
4.一个实例实现音频捕获
实例有两个文件组成。CaptureAudio.java实现
①查询、获得音频采集设备。
②捕获音频。
③将音频保存到本地文件foo.wav。
StateHelper实现处理器(processor)的状态控制管理。
以下为流程图:
5.音频捕获代码实例:
CaptureAudio.java
import java.io.IOException;
import java.util.Vector;
import javax.media.CaptureDeviceInfo;
import javax.media.CaptureDeviceManager;
import javax.media.DataSink;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.NoDataSinkException;
import javax.media.NoProcessorException;
import javax.media.Processor;
import javax.media.control.StreamWriterControl;
import javax.media.format.AudioFormat;
import javax.media.protocol.DataSource;
import javax.media.protocol.FileTypeDescriptor;
public class CaptureAudio {
/**
* Writing captured audio to a file with a DataSink.
*/
public static void main(String[] args) {
CaptureDeviceInfo di = null;
Processor p = null;
StateHelper sh = null;
//查询CaptureDeviceManager,来定位你需要使用的媒体采集设备。
Vector deviceList = CaptureDeviceManager.getDeviceList(new
AudioFormat(AudioFormat.LINEAR, 44100, 16, 2));
if (deviceList.size() > 0){
//得到此设备的CaptureDeviceInfo实例。
di = (CaptureDeviceInfo)deviceList.firstElement();
}
else
// 找不到满足(linear, 44100Hz, 16 bit,stereo audio.)音频设备,退出。
System.exit(-1);
try {
//获得MediaLocator,并由此创建一个Processor。
p = Manager.createProcessor(di.getLocator());
sh = new StateHelper(p);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
} catch (NoProcessorException e) {
e.printStackTrace();
System.exit(-1);
}
// Configure the processor
if (!sh.configure(10000)){
System.out.println("configure wrong!");
System.exit(-1);
}
//定义待存储该媒体的内容类型(content type)。
p.setContentDescriptor(new
FileTypeDescriptor(FileTypeDescriptor.WAVE));
// realize the processor.
if (!sh.realize(10000)){
System.out.println("realize wrong!");
System.exit(-1);
}
// get the output of the processor
DataSource source = p.getDataOutput();
//定义存储该媒体的文件。
MediaLocator dest = new MediaLocator(new java.lang.String(
"file:///D:/Dvp/workspace/JavaSoundMedia/foo.wav"));
//创建一个数据池
DataSink filewriter = null;
try {
filewriter = Manager.createDataSink(source, dest);
filewriter.open();
} catch (NoDataSinkException e) {
e.printStackTrace();
System.exit(-1);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
} catch (SecurityException e) {
e.printStackTrace();
System.exit(-1);
}
// if the Processor implements StreamWriterControl, we can
// call setStreamSizeLimit
// to set a limit on the size of the file that is written.
StreamWriterControl swc = (StreamWriterControl)
p.getControl("javax.media.control.StreamWriterControl");
//set limit to 5MB
if (swc != null)
swc.setStreamSizeLimit(5000000);
// now start the filewriter and processor
try {
filewriter.start();
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
// Capture for 5 seconds
sh.playToEndOfMedia(5000);
sh.close();
// Wait for an EndOfStream from the DataSink and close it...
filewriter.close();
}
}
|
StateHelper.java
import javax.media.*;
public class StateHelper implements javax.media.ControllerListener {
Player player = null;
boolean configured = false;
boolean realized = false;
boolean prefetched = false;
boolean eom = false;//End of media.
boolean failed = false;
boolean closed = false;
public StateHelper(Player p) {
player = p;
p.addControllerListener(this);
}
/**
* To judge whether the processor is configured.
* Configure the processor in the given time which is limited
* by the timeOutMillis.Once a Processor is Configured, you
* can set its output format and TrackControl options.
*/
public boolean configure(int timeOutMillis) {
long startTime = System.currentTimeMillis();
synchronized (this) {
if (player instanceof Processor)
((Processor)player).configure();
else
return false;
while (!configured && !failed) {
try {
wait(timeOutMillis);
} catch (InterruptedException ie) {
}
if (System.currentTimeMillis() - startTime > timeOutMillis)
break;
}
}
return configured;
}
/**
* To judge whether the playerr is realized.
*/
public boolean realize(int timeOutMillis) {
long startTime = System.currentTimeMillis();
synchronized (this) {
player.realize();
while (!realized && !failed) {
try {
wait(timeOutMillis);
} catch (InterruptedException ie) {
}
if (System.currentTimeMillis() - startTime > timeOutMillis)
break;
}
}
return realized;
}
/**
* To judge whether the player is prefetched.
*/
public boolean prefetch(int timeOutMillis) {
long startTime = System.currentTimeMillis();
synchronized (this) {
player.prefetch();
while (!prefetched && !failed) {
try {
wait(timeOutMillis);
} catch (InterruptedException ie) {
}
if (System.currentTimeMillis() - startTime > timeOutMillis)
break;
}
}
return prefetched && !failed;
}
/**
* To judge whether the player has finished.
*/
public boolean playToEndOfMedia(int timeOutMillis) {
long startTime = System.currentTimeMillis();
eom = false;
synchronized (this) {
player.start();
while (!eom && !failed) {
try {
wait(timeOutMillis);
} catch (InterruptedException ie) {
}
if (System.currentTimeMillis() - startTime > timeOutMillis)
break;
}
}
return eom && !failed;
}
public void close() {
synchronized (this) {
player.close();
while (!closed) {
try {
wait(100);
} catch (InterruptedException ie) {
}
}
}
player.removeControllerListener(this);
}
public synchronized void controllerUpdate(ControllerEvent ce) {
if (ce instanceof RealizeCompleteEvent) {
realized = true;
} else if (ce instanceof ConfigureCompleteEvent) {
configured = true;
} else if (ce instanceof PrefetchCompleteEvent) {
prefetched = true;
} else if (ce instanceof EndOfMediaEvent) {
eom = true;
} else if (ce instanceof ControllerErrorEvent) {
failed = true;
} else if (ce instanceof ControllerClosedEvent) {
closed = true;
} else {
return;
}
notifyAll();
}
}
|
本文转自zhangjunhd51CTO博客,原文链接:http://blog.51cto.com/zhangjunhd/25475,如需转载请自行联系原作者