JMF ,RTP流的录音保存问题?

package gov.nist.applet.phone.media.messaging;

import java.awt.FileDialog;
import java.awt.Frame;
import java.io.IOException;

import javax.media.CannotRealizeException;
import javax.media.ConfigureCompleteEvent;
import javax.media.ControllerEvent;
import javax.media.ControllerListener;
import javax.media.DataSink;
import javax.media.Format;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.NoDataSinkException;
import javax.media.NoProcessorException;
import javax.media.NotConfiguredError;
import javax.media.Player;
import javax.media.Processor;
import javax.media.ProcessorModel;
import javax.media.RealizeCompleteEvent;
import javax.media.control.TrackControl;
import javax.media.format.AudioFormat;
import javax.media.format.VideoFormat;
import javax.media.protocol.DataSource;
import javax.media.protocol.FileTypeDescriptor;


//import jmapps.util.StateHelper;

public class SaveAudioVideo2File {

/**
* @param args
*/
Processor processor;
DataSource dataSource;
DataSink dataSink;
StateHelper state;
MediaLocator mediaLocator;
boolean encodingOK = false;


public boolean record(DataSource ds)
{

try {

this.processor = Manager.createProcessor(ds);

} catch (Exception e1)
{
System.err.println("no such processor exception");
e1.printStackTrace();
return false;
}
this.state = new StateHelper(processor);
if(!state.configure(1000))
{
System.out.println("configure error :");
return false;
}

// // 设置存储录像文件的格式为 .QUICKTIME
processor.setContentDescriptor(new FileTypeDescriptor(FileTypeDescriptor.QUICKTIME));

// realize the processor,让 processor 进入 realized 状态
if (!state.realize(1000)) {
System.out.println("realize error!");
return false;
}

boolean encodingOK = false;

encodingOK = setTracks(processor, encodingOK);
if(!encodingOK)
{
System.err.println("encoding error!");
return false;
}

try
{
this.dataSink = Manager.createDataSink(processor.getDataOutput(), getMediaLocator());
} catch (NoDataSinkException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}

try
{
dataSink.open();
dataSink.start();
} catch (SecurityException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
return false;
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}

processor.start();
return true;
}

private MediaLocator getMediaLocator()
{

Frame saveVideoFrame = new Frame("保存视频文件");
FileDialog saveVideoFileDialog = new FileDialog(saveVideoFrame, "保存视频文件", FileDialog.SAVE);
saveVideoFileDialog.setFile(".mov");
saveVideoFileDialog.setVisible(true);
String videoFileSavePath = saveVideoFileDialog.getDirectory();
String videoFileSaveName = saveVideoFileDialog.getFile();
if (videoFileSaveName != null) {
videoFileSavePath = videoFileSavePath.replace("\\", "/");
String destinationString = "file:///" + videoFileSavePath + videoFileSaveName;
MediaLocator mediaLocator = new MediaLocator(destinationString);
return mediaLocator;
}
//if a user not choose a file path,then
return new MediaLocator("file://d:/media.mov");
}
public void stopRecord()
{

dataSink.close();
processor.close();
processor.deallocate();//回收内存
processor = null;



}
public void setDataSource(DataSource ds)
{
this.dataSource = ds;
}
/**
* save the position you wanted to save this file
* @param ml
*/
public void setMediaLocator(MediaLocator ml)
{
this.mediaLocator = ml;
}
private static boolean setTracks(Processor p, boolean encodingOK)
throws NotConfiguredError
{
TrackControl tracks[] = p.getTrackControls();
for(int i=0;i<tracks.length;i++)
{
if(tracks[i].getFormat() instanceof AudioFormat)
{
tracks[i].setFormat(new AudioFormat(AudioFormat.IMA4));
encodingOK = true;
}
else if(tracks[i].getFormat() instanceof VideoFormat)
{
tracks[i].setFormat(new VideoFormat(VideoFormat.H263));
encodingOK = true;
}
else
tracks[i].setEnabled(false);
}
return encodingOK;
}

public class StateHelper implements ControllerListener {
Player xplayer = 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) {
xplayer = p;
p.addControllerListener(this);
}

public boolean configure(int timeOutMillis) {
// RealizeCompleteEvent 发生了的话使 ce 事件与之比较,若相等,那么 realized 为 true。
/*
* 监听 ConfigureCompleteEvent 和 ConfigureCompleteEvent 事件的发生。
* 如 ConfigureCompleteEvent 事件发生,那么就会赋给 configured 为 ture, 使得 public
* boolean configure 方法中的 while (!configured && !failed){} 这个循环退出。
*/
long startTime = System.currentTimeMillis();
synchronized (this) {
if (xplayer instanceof Processor) {
((Processor) xplayer).configure();
} else {
return false;
}
while (!configured && !failed) {
try {
wait(timeOutMillis);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
if (System.currentTimeMillis() - startTime > timeOutMillis) {
break;
}
}
}
return configured;
}

public boolean realize(int timeOutMillis) {
long startTime = System.currentTimeMillis();
synchronized (this) {
xplayer.realize();
while (!realized && !failed) {
try {
wait(timeOutMillis);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
if (System.currentTimeMillis() - startTime > timeOutMillis) {
break;
}
}
}
return realized;
}

public synchronized void controllerUpdate(ControllerEvent ce) {
if (ce instanceof RealizeCompleteEvent) {
realized = true;
} else if (ce instanceof ConfigureCompleteEvent) {
configured = true;
} else {
return;
}
notifyAll();
}
}

}


调用这个类的时候,我传过来的参数是通过RTPManager 管理接收的RTP流,通过update()方法中监听NewReceiverStream事件,当收到一个NewStream的时候,stream=((NewStreamEvent)event).getReceiveStream().DataSource ds = stream.getDataSource();

我建立了2个RTP流,一个是视频,一个是音频的。

if (ctl.getFormat() instanceof VideoFormat)
{
PlayerWindow pw = new PlayerWindow(p, stream);
playerWindows.addElement(pw);
videoDataSource = ((SourceCloneable)clonedSource).createClone();
}

else if(ctl.getFormat() instanceof AudioFormat)
{
DataSource clonedDataSource3 = ((SourceCloneable)clonedSource).createClone();
audioDataSource = clonedDataSource3;
}


saveMedia = new SaveAudioVideo2File();
if(videoDataSource!=null&&audioDataSource!=null)
{
try
{
mergeDataSource = Manager.createMergingDataSource(
new DataSource[]{audioDataSource,videoDataSource,});
saveMedia.record(mergeDataSource);
} catch (IncompatibleSourceException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else if(videoDataSource!=null)
{
saveMedia.record(videoDataSource);
}
else if(audioDataSource!=null)
{
saveMedia.record(audioDataSource);
}


通过Debug调试可以看到创建的是克隆的混合的DataSource,当录音的时候,就会出现不可以Configure the processor 的异常。我一直找不到为什么不可以configure,请问哪位大侠可以指点一二不?急急!!1111111111111
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,我们需要添加依赖,这里我们使用maven管理项目,所以在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>javax.media</groupId> <artifactId>jmf</artifactId> <version>2.1.1e</version> </dependency> ``` 接下来我们创建一个RTP服务类,并实现接收RTP的方法: ```java import javax.media.Manager; import javax.media.MediaLocator; import javax.media.Player; import javax.media.protocol.DataSource; public class RtpService { private Player player; private String url; public RtpService(String url) { this.url = url; } // 启动RTP服务 public void start() throws Exception { MediaLocator ml = new MediaLocator(url); DataSource ds = Manager.createDataSource(ml); player = Manager.createPlayer(ds); player.start(); } // 停止RTP服务 public void stop() { if (player != null) { player.stop(); player.close(); player = null; } } } ``` 上述代码中,我们创建了一个RTP服务类,它有一个构造函数,用于传入RTP的URL。start方法用于启动RTP服务,它会根据传入的URL创建一个MediaLocator对象,并从该对象中创建数据源(DataSource)。然后使用Manager.createPlayer(ds)方法创建一个播放器(Player),最后调用player.start()方法开始播放RTP。stop方法用于停止RTP服务,它会停止播放器(Player)并关闭它。 下面给出一个使用案例,我们使用Spring Boot框架创建一个Web应用程序,然后在Controller中调用RtpService类的start方法启动RTP服务。当请求“/start”时,启动RTP服务;请求“/stop”时,停止RTP服务。 ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class RtpController { private RtpService rtpService; @Autowired public RtpController(RtpService rtpService) { this.rtpService = rtpService; } @GetMapping("/start") public String start() { try { rtpService.start(); return "RTP service started."; } catch (Exception e) { return "Failed to start RTP service: " + e.getMessage(); } } @GetMapping("/stop") public String stop() { rtpService.stop(); return "RTP service stopped."; } } ``` 上述代码中,我们创建了一个RtpController类,用于处理Web请求。在构造函数中,我们注入了一个RtpService对象。start方法处理“/start”请求,它会调用RtpService类的start方法启动RTP服务。stop方法处理“/stop”请求,它会调用RtpService类的stop方法停止RTP服务。当RTP服务启动成功时,start方法会返回“RTP service started.”;当RTP服务启动失败时,start方法会返回“Failed to start RTP service: ”加上错误信息。 最后,在Spring Boot的启动类中,我们添加了@EnableAutoConfiguration注解,用于自动配置Spring Boot应用程序所需的bean。 ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @EnableAutoConfiguration public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 至此,我们就完成了使用Spring Boot集成JMF开启RTP服务,接收RTP的过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值