我正在研究Java中的mp3流媒体应用程序。服务器端的用户在服务器端播放音乐文件(尽管服务器当前正在发送文件),并且客户端的播放器读取流并播放音乐。我正在使用JLayer播放音乐文件。服务器以块的形式发送文件,并以块的形式接收文件并播放它。我正在使用jgroups库进行组成员资格管理,因为我计划扩展许多客户端使用的应用程序。这是我到目前为止所尝试的:
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");
}
}
根据我当前的实现,播放器只播放一帧,但我希望它能够播放收到的整个mp3文件。我在这做错了什么?如何同步服务器和客户端,以便客户端在收到文件后立即播放整个流?欢迎任何建议。