經過幾天搜索SO和谷歌我開始放棄,所以我想我不妨在這裏發帖。Android:將相機作爲mjpeg流式傳輸
我正在創建一個應用程序,應該提供某種視頻聊天。因爲這應該儘可能接近實時,所以我閱讀了各種協議,並決定嘗試MJPEG作爲初學者(現在不涉及音頻)。
現在流式傳輸數據讓我瘋狂。連接建立後,應用程序開始將相機預覽幀寫入流,但VLC和mplayer都不開始播放視頻。監視連接顯示數據正在到達。
連接 此代碼是由一個異步任務執行的監聽器通知上的成功:
try
{
ServerSocket server = new ServerSocket(8080);
socket = server.accept();
server.close();
Log.i(TAG, "New connection to :" + socket.getInetAddress());
stream = new DataOutputStream(socket.getOutputStream());
prepared = true;
}
catch (IOException e)
{
Log.e(TAG, e.getMessage();
}
我的電腦上我執行「mplayer的http://tabletIP:8080
」和平板登記的連接(於是開始我的流光和相機預覽)。這也適用於VLC。
流這寫頭流:
if (stream != null)
{
try
{
// send the header
stream.write(("HTTP/1.0 200 OK\r\n" +
"Server: iRecon\r\n" +
"Connection: close\r\n" +
"Max-Age: 0\r\n" +
"Expires: 0\r\n" +
"Cache-Control: no-cache, private\r\n" +
"Pragma: no-cache\r\n" +
"Content-Type: multipart/x-mixed-replace; " +
"boundary=--" + boundary +
"\r\n\r\n").getBytes());
stream.flush();
streaming = true;
}
catch (IOException e)
{
notifyOnEncoderError(this, "Error while writing header: " + e.getMessage());
stop();
}
}
之後數據流是通過Camera.onPreviewFrame()回調觸發:
@Override
public void onPreviewFrame(byte[] data, Camera camera)
{
frame = data;
if (streaming)
mHandler.post(this);
}
@Override
public void run()
{
// TODO: cache not filling?
try
{
// buffer is a ByteArrayOutputStream
buffer.reset();
switch (imageFormat)
{
case ImageFormat.JPEG:
// nothing to do, leave it that way
buffer.write(frame);
break;
case ImageFormat.NV16:
case ImageFormat.NV21:
case ImageFormat.YUY2:
case ImageFormat.YV12:
new YuvImage(frame, imageFormat, w, h, null).compressToJpeg(area, 100, buffer);
break;
default:
throw new IOException("Error while encoding: unsupported image format");
}
buffer.flush();
// write the content header
stream.write(("--" + boundary + "\r\n" +
"Content-type: image/jpg\r\n" +
"Content-Length: " + buffer.size() +
"\r\n\r\n").getBytes());
// Should omit the array copy
buffer.writeTo(stream);
stream.write("\r\n\r\n".getBytes());
stream.flush();
}
catch (IOException e)
{
stop();
notifyOnEncoderError(this, e.getMessage());
}
}
沒有拋出異常。 mHandler運行在它自己的HandlerThread中。只是爲了確定我嘗試使用AsyncTask,無濟於事(順便說一句,這是更好?)。
編碼的框架在android端很好,我將它們保存到jpg文件並可以打開它們。
我的猜測是我必須以某種方式將數據聚類在一起,或者必須爲套接字或某些東西設置一些選項,但....好吧,我卡住了。
TL;博士: VLC不打流,mplayer的說 '不緩存填充',可能是在最後的代碼段的問題,需要幫助〜:)
太感謝您了!
你可以請發佈代碼從相機獲取MJPEG。 – Sourav301 2014-01-21 09:06:39
@Sourav你的課必須實現Camera.PreviewCallback。初始化相機調用camera.setPreviewCallback(...)後。其餘的檢索JPEGS已經在我的問題。 – Managarm 2014-02-10 13:40:08
對於那些想知道應該是什麼邊界的人來說,它可以是任何Java字符串(由字母組成,不知道數字和特殊字符是否可以工作)。 – 2015-06-10 21:15:51