Java 使用jlayer重复播放流式mp3数据
我正在用Java开发一个mp3流媒体应用程序。服务器端的用户在服务器端播放音乐文件(尽管服务器当前正在发送文件),客户端的播放器读取流并播放音乐。我正在使用JLayer播放音乐文件。服务器分块发送文件,也分块接收并播放文件。我正在使用库进行组成员管理,因为我计划扩展应用程序以供许多客户使用。以下是我迄今为止所尝试的:Java 使用jlayer重复播放流式mp3数据,java,streaming,jgroups,jlayer,Java,Streaming,Jgroups,Jlayer,我正在用Java开发一个mp3流媒体应用程序。服务器端的用户在服务器端播放音乐文件(尽管服务器当前正在发送文件),客户端的播放器读取流并播放音乐。我正在使用JLayer播放音乐文件。服务器分块发送文件,也分块接收并播放文件。我正在使用库进行组成员管理,因为我计划扩展应用程序以供许多客户使用。以下是我迄今为止所尝试的: import javazoom.jl.decoder.JavaLayerException; import javazoom.jl.player.Player; import or
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.Player;
import org.apache.commons.io.input.CountingInputStream;
import org.jgroups.*;
import org.jgroups.conf.ClassConfigurator;
import org.jgroups.util.Util;
import java.io.*;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Created by Xabush on 1/25/2016 21:43.
* Project: DSP_Java
*/
public class SimpleMPlayer extends ReceiverAdapter {
private CountingInputStream in;
private Player player;
private String filename;
protected File file;
protected int offest = 0;
protected JChannel channel;
protected int frames;
protected boolean isServer = true;
protected Map<String, OutputStream> files = new ConcurrentHashMap<String, OutputStream>();
protected static final short ID = 3500;
public SimpleMPlayer(String filename) throws IOException, JavaLayerException {
this.filename = filename;
file = new File(this.filename);
in = new CountingInputStream(new FileInputStream(filename));
player = new Player(new FileInputStream("src/np/test.mp3"));
}
public void start(String name) throws Exception {
ClassConfigurator.add((short) 3500, FileHeader.class);
channel = new JChannel("src/jgroups/fast.xml").name(name);
channel.setReceiver(this);
channel.connect("File_Cluster");
if (isServer)
eventLoop();
}
private void eventLoop() throws Exception {
Util.keyPress(String.format("<enter to send %s>\n", file.getName()));
sendFile();
System.out.print("Finished sending file");
}
protected void sendFile() throws Exception {
try {
int read = 0;
while (read != -1) {
byte[] buff = new byte[2304];
read = in.read(buff);
offest += in.getByteCount();
frames += 1;
sendMessage(buff, 0, buff.length, false, frames);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
sendMessage(null, 0, 0, true, frames);
}
}
protected void sendMessage(byte[] buf, int offset, int length, boolean eof, int fr) throws Exception {
Message msg = new Message(null, buf, offset, length).putHeader(ID, new FileHeader(filename, eof, fr));
// set this if the sender doesn't want to receive the file
msg.setTransientFlag(Message.TransientFlag.DONT_LOOPBACK);
channel.send(msg);
}
public void receive(Message msg) {
byte[] buf = msg.getRawBuffer();
FileHeader hdr = (FileHeader) msg.getHeader(ID);
if (hdr == null)
return;
OutputStream out = files.get(hdr.filename);
int frame = hdr.frame;
try {
if (out == null) {
File tmp = new File(hdr.filename);
String fname = tmp.getName();
fname = "src/np/" + fname;
out = new FileOutputStream(fname);
files.put(hdr.filename, out);
}
if (hdr.eof) {
Util.close(files.remove(hdr.filename));
} else {
out.write(msg.getRawBuffer(), msg.getOffset(), msg.getLength());
playFromStream(frame);
}
} catch (Throwable t) {
System.err.println(t);
}
}
public void playFromStream(int fr) throws IOException {
try {
player.play(fr);
} catch (JavaLayerException e) {
player.close();
e.printStackTrace();
}
}
public boolean isServer() {
return isServer;
}
public void setServer(boolean server) {
isServer = server;
}
protected static class FileHeader extends Header {
protected String filename;
protected boolean eof;
protected int frame;
public FileHeader() {
} // for de-serialization
public FileHeader(String filename, boolean eof, int fr) {
this.filename = filename;
this.eof = eof;
this.frame = fr;
}
public int size() {
return Util.size(filename) + Global.BYTE_SIZE;
}
public void writeTo(DataOutput out) throws Exception {
Util.writeObject(filename, out);
out.writeBoolean(eof);
out.writeInt(frame);
}
public void readFrom(DataInput in) throws Exception {
filename = (String) Util.readObject(in);
eof = in.readBoolean();
frame = in.readInt();
}
}
public static void main(String[] args) throws Exception {
SimpleMPlayer mplayer = new SimpleMPlayer("src/jgroups/test.mp3"); // name and file
if (args[0].equalsIgnoreCase("server")) {
mplayer.setServer(true);
} else {
mplayer.setServer(false);
}
mplayer.start("MusicChannel");
}
}
导入javazoom.jl.decoder.JavaLayerException;
导入javazoom.jl.player.player;
导入org.apache.commons.io.input.CountingInputStream;
导入org.jgroups.*;
导入org.jgroups.conf.ClassConfigurator;
导入org.jgroups.util.util;
导入java.io.*;
导入java.util.Map;
导入java.util.concurrent.ConcurrentHashMap;
/**
*由Xabush于2016年1月25日21:43创建。
*项目:DSP_Java
*/
公共类SimplePlayer扩展了ReceiverAdapter{
私有计数输入流;
私人玩家;
私有字符串文件名;
受保护的文件;
受保护的int offest=0;
保护JChannel信道;
受保护的int帧;
受保护的布尔值isServer=true;
受保护的映射文件=新的ConcurrentHashMap();
受保护静态最终短路ID=3500;
公共SimplePlayer(字符串文件名)抛出IOException、JavaLayerException{
this.filename=文件名;
file=新文件(此.filename);
in=新计数输入流(新文件输入流(文件名));
player=新播放器(新文件输入流(“src/np/test.mp3”);
}
public void start(字符串名称)引发异常{
添加((短)3500,FileHeader.class);
channel=newjchannel(“src/jgroups/fast.xml”).name(name);
信道设置接收器(本);
channel.connect(“文件集群”);
如果(isServer)
eventLoop();
}
私有void eventLoop()引发异常{
Util.keyPress(String.format(“\n”,file.getName());
sendFile();
系统输出打印(“已完成发送文件”);
}
受保护的void sendFile()引发异常{
试一试{
int read=0;
while(读取!=-1){
字节[]buff=新字节[2304];
read=in.read(buff);
offest+=in.getByteCount();
帧+=1;
sendMessage(buff,0,buff.length,false,frames);
}
}捕获(例外e){
e、 printStackTrace();
}最后{
sendMessage(null、0、0、true、帧);
}
}
受保护的void sendMessage(字节[]buf,整数偏移量,整数长度,布尔eof,整数fr)引发异常{
Message msg=新消息(null、buf、偏移量、长度).putHeader(ID、新文件头(文件名、eof、fr));
//如果发件人不想接收文件,请设置此选项
msg.setTransientFlag(Message.TransientFlag.DONT_环回);
频道发送(msg);
}
公共无效接收(消息消息消息){
字节[]buf=msg.getRawBuffer();
FileHeader hdr=(FileHeader)msg.getHeader(ID);
如果(hdr==null)
返回;
OutputStream out=files.get(hdr.filename);
int frame=hdr.frame;
试一试{
if(out==null){
文件tmp=新文件(hdr.filename);
字符串fname=tmp.getName();
fname=“src/np/”+fname;
out=新文件输出流(fname);
files.put(hdr.filename,out);
}
如果(hdr.eof){
Util.close(files.remove(hdr.filename));
}否则{
write(msg.getRawBuffer(),msg.getOffset(),msg.getLength());
playFromStream(帧);
}
}捕获(可丢弃的t){
系统错误println(t);
}
}
公共void playFromStream(int-fr)引发IOException{
试一试{
player.play(fr);
}捕获(JavaLayerXe){
player.close();
e、 printStackTrace();
}
}
公共布尔值isServer(){
返回isServer;
}
公共void设置服务器(布尔服务器){
isServer=服务器;
}
受保护的静态类FileHeader扩展标头{
受保护的字符串文件名;
保护布尔eof;
受保护的int帧;
公共文件头(){
}//用于反序列化
公共文件头(字符串文件名、布尔eof、整数fr){
this.filename=文件名;
this.eof=eof;
this.frame=fr;
}
公共整数大小(){
返回Util.size(文件名)+Global.BYTE\u size;
}
public void writeTo(DataOutput out)引发异常{
Util.writeObject(文件名,out);
out.writebolean(eof);
out.writeInt(帧);
}
public void readFrom(DataInput in)引发异常{
filename=(字符串)Util.readObject(in);
eof=in.readBoolean();
frame=in.readInt();
}
}
公共静态void main(字符串[]args)引发异常{
SimpleMPlayer-mplayer=newsimplemplayer(“src/jgroups/test.mp3”);//名称和文件
if(参数[0].equalsIgnoreCase(“服务器”)){
mplayer.setServer(true);
}否则{
mplayer.setServer(false);
}
mplayer.start(“音乐频道”);
}
}
在我当前的实现中,播放器只播放一帧,但我希望它在接收时播放整个mp3文件。我做错了什么?如何同步服务器和客户端,以便客户端在收到文件后立即播放整个流?欢迎提出任何建议