我正在處理將從IP攝像頭流式傳輸視頻的Java應用程序。來自IP攝像機的視頻以MJPEG格式傳輸。該協議是以下...讀取二進制流,直到遇到「 r n」
--ipcamera (\r\n)
Content-Type: image/jpeg (\r\n)
Content-Length: {length of frame} (\r\n)
(\r\n)
{frame}
(\r\n)
--ipcamera (\r\n)
etc.
我已經使用了類如的BufferedReader和掃描器讀取,直到「\ r \ n」個嘗試,但那些都是爲了文本而不是二進制數據,所以它變得腐敗。有沒有什麼方法可以讀取二進制流,直到遇到「\ r \ n」?這是我目前的(破碎的)代碼。
編輯:我已經得到它的工作。我更新了下面的代碼。但是,這樣做確實很慢。我不確定它是否與ArrayList有關,但它可能是罪魁禍首。任何指針來加速代碼?目前對於單幀來說,它需要500ms到900ms。
public void run() {
long startTime = System.currentTimeMillis();
try {
URLConnection urlConn = url.openConnection();
urlConn.setReadTimeout(15000);
urlConn.connect();
urlStream = urlConn.getInputStream();
DataInputStream dis = new DataInputStream(urlStream);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ArrayList<Byte> bytes = new ArrayList<Byte>();
byte cur;
int curi;
byte[] curBytes;
int length = 0;
while ((curi = dis.read()) != -1) {
cur = (byte) curi;
bytes.add(cur);
curBytes = getPrimativeArray(bytes);
String curBytesString = new String(curBytes, "UTF-8");
if (curBytesString.equals("--ipcamera\r\n")) {
bytes.clear();
continue;
} else if (curBytesString.equals("Content-Type: image/jpeg\r\n")) {
bytes.clear();
continue;
} else if (curBytesString.matches("^Content-Length: ([0-9]+)\r\n$")) {
length = Integer.parseInt(curBytesString.replace("Content-Length: ", "").trim());
bytes.clear();
continue;
} else if (curBytesString.equals("\r\n")) {
if (length == 0) {
continue;
}
byte[] frame = new byte[length];
dis.readFully(frame, 0, length);
writeFrame(frame);
bytes.clear();
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
long curTime = System.currentTimeMillis() - startTime;
System.out.println(curTime);
}
private byte[] getPrimativeArray(ArrayList<Byte> array) {
byte[] bytes = new byte[array.size()];
for (int i = 0; i < array.size(); i++) {
bytes[i] = array.get(i).byteValue();
}
return bytes;
}
private void writeFrame(byte[] bytes) throws IOException {
File file = new File("C:\\test.jpg");
FileOutputStream fos = new FileOutputStream(file);
fos.write(bytes);
fos.close();
System.out.println("done");
}
是的,我沒有意識到BufferedReader只用於文本。這是有道理的考慮它返回一個char [],哈哈。除非找到「\ r \ n」,否則還有其他閱讀方式嗎?我不希望在DataInputStream中使用readLine(),因爲它已被棄用。我嘗試過使用Scanner類,但它就像BufferedReader並且用於文本。 – CharDev
DataInputStream.readLine()已被棄用,因爲它讀取文本,但假定ISO-8859-1編碼,我懷疑你的情況是好的。你可以寫你自己的readLine()方法,但我認爲它最終會做同樣的事情。有時候最簡單的選擇是不推薦使用的方法。 –
我使用ArrayList讀取頭文件,然後在得到長度並找到「\ r \ n」後將其餘的文件讀入到byte []中。但是,它非常慢(500ms-900ms)。任何指針? –
CharDev