public void dosend()
{
Processor p=null;
// First find a capture device that will capture linear audio
// data at 8bit 8Khz
AudioFormat format= new AudioFormat(AudioFormat.LINEAR,
8000,
8,
1);
Vector devices= CaptureDeviceManager.getDeviceList( format);
CaptureDeviceInfo di= null;
if (devices.size() > 0) {
di = (CaptureDeviceInfo) devices.elementAt(0);
System.out.print(di.getName());
}
else {
// exit if we could not find the relevant capturedevice.
System.exit(-1);
}
// Create a processor for this capturedevice & exit if we
// cannot create it
try {
p=Manager.createProcessor(di.getLocator());
} catch (IOException e) {
System.exit(-1);
} catch (NoProcessorException e) {
System.exit(-1);
}
// configure the processor
try{
p.configure();
// p.realize();
}
catch(Exception eee)
{
System.out.print(eee);
}
System.out.print(p.getState());
System.out.print(p.Configuring);
// System.out.print(p.getContentDescriptor().toString());
// block until it has been configured
// test.setContentDescriptor(
// new ContentDescriptor( ContentDescriptor.RAW));
System.exit(-1);
/*TrackControl track[] = p.getTrackControls();
boolean encodingOk = false;
// Go through the tracks and try to program one of them to
// output gsm data.
for (int i = 0; i < track.length; i++) {
if (!encodingOk && track[i] instanceof FormatControl) {
if (((FormatControl)track[i]).
setFormat( new AudioFormat(AudioFormat.GSM_RTP,
8000,
8,
1)) == null) {
track[i].setEnabled(false);
}
else {
encodingOk = true;
}
} else {
// we could not set this track to gsm, so disable it
track[i].setEnabled(false);
}
}
// At this point, we have determined where we can send out
// gsm data or not.
// realize the processor
if (encodingOk) {
p.realize();
// block until realized.
// get the output datasource of the processor and exit
// if we fail
DataSource ds = null;
try {
ds = p.getDataOutput();
} catch (NotRealizedError e) {
System.exit(-1);
}
// hand this datasource to manager for creating an RTP
// datasink our RTP datasimnk will multicast the audio
try {
String url= "rtp://224.144.251.104:49150/audio/1";
MediaLocator m = new MediaLocator(url);
DataSink d = Manager.createDataSink(ds, m);
d.open();
d.start();
} catch (Exception e) {
System.exit(-1);
}
}
*/
}
JMF为存取特定的动画帧提供了一种高级存取方式。下面的代码片断显示了该高级方式的主要组成,我略去了其中有关错误检测及异常处理的部分。
//在realized状态下,创建一个动画播放器
URL url = new URL("file:" + movieFnm);
Player p = Manager.createRealizedPlayer(url);
//生成一个帧放置器
FramePositioningControl fpc = (FramePositioningControl) p.getControl("javax.media.control. FramePositioningControl");
//创建一个帧抓取器
FrameGrabbingControl fg = (FrameGrabbingControl) p.getControl("javax.media.control.FrameGrabbingControl");
//
改变到一个prefetched 态
p.prefetch();
//一直等待,直到播放器处于那种状态...
//移动到具体的某帧,例如第100帧
fpc.seek(100);
//取得当前帧的一个快照
Buffer buf = fg.grabFrame();
//取得它的视频格式细节
VideoFormat vf = (VideoFormat) buf.getFormat();
//用视频格式初始化BufferToImage
BufferToImage bufferToImage =new BufferToImage(vf);
//把缓冲区数据转化成一幅图像
Image im = bufferToImage.createImage(buf);
//指定想得到的BufferedImage的格式
BufferedImage formatImg =
new BufferedImage(
FORMAT_SIZE, FORMAT_SIZE,
BufferedImage.TYPE_3BYTE_BGR);
//把该图像转化成一个BufferedImage
Graphics g = formatImg.getGraphics();
g.drawImage(im, 0, 0,
FORMAT_SIZE, FORMAT_SIZE, null);
g.dispose();
一个媒体播放器从创建到开始播放共经历6种状态。处于realized态的播放器知道如何对其数据进行着色,所以在要求时可以提供可视化组件和控件。我用了两个控件:FramePositioningControl 和FrameGrabbingControl。FramePositioningControl提供seek()和skip()等方法,用于在一个动画中移动以查找一个特别的帧。FrameGrabbingControl提供了方法grabFrame(),它可以从动画的视频轨道中抓取当前帧。
为使这些控件工作,播放器必须实现从realized 态转入prefetched 态。这可以使播放器为进行媒体播放作好准备,并使媒体数据装入。
对于prefetch()的调用是异步的,这意味着我的代码必须包含一个等待周期,直到完成一个变换状态为止。
的JMF编码
是实现一个waitForState()方法,它可以停止代码的执行,直到一个状态改变事件唤醒它。
要抓取的帧可以用seek()方法在轨道中定位,然后调用grabFrame()方法实现帧的抓取。编码中必须经历多个转换步骤来把抓取的缓冲对象转换成JMFMovieScreen要求的BufferedImage对象。注意,BufferedImage对象使用了TYPE_3BYTE_BGR格式,这种格式对于该程序中的Java 3D部分通过引用方式使用纹理是必需的。
Sun的JMF站点 包括了一些有用的小例子,其中Seek.java一例说明了如何使用FramePositioningControl来遍历一个动画。