Android:以mjpeg格式传输相机

经过几天的搜索SO和Google之后,我开始放弃了,所以我认为最好还是在这里发布。

我正在创建一个应该提供某种视频聊天功能的android应用。由于这应该尽可能接近实时,因此我阅读了各种协议,并决定尝试使用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();

}

在我的PC上,我执行’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文件并可以打开它们。

我的猜测是,我必须以某种方式对数据进行聚类,或者必须为套接字或其他内容设置一些选项,但是…。

VLC没有播放流,mplayer说“缓存未填充”,问题可能在最后一个代码段中,需要帮助〜:)

非常感谢你!

回答:

我知道了。好像我的http- / content-headers被弄乱了。正确的标题应该是:

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-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0\r\n" +

"Pragma: no-cache\r\n" +

"Content-Type: multipart/x-mixed-replace; " +

"boundary=" + boundary + "\r\n" +

"\r\n" +

"--" + boundary + "\r\n").getBytes());

stream.write(("Content-type: image/jpeg\r\n" +

"Content-Length: " + buffer.size() + "\r\n" +

"X-Timestamp:" + timestamp + "\r\n" +

"\r\n").getBytes());

buffer.writeTo(stream);

stream.write(("\r\n--" + boundary + "\r\n").getBytes());

当然,将边界置于何处是您自己的选择。也可能有些字段是可选的(例如,大多数在Cache-

Control中),但这是可行的,直到现在,我还是懒得剥夺它们。重要的是要记住换行符(\r\nthingies)…

以上是 Android:以mjpeg格式传输相机 的全部内容, 来源链接: utcz.com/qa/430442.html

回到顶部