安卓:流媒体的相机MJPEG [英] Android: streaming the camera as mjpeg

查看:235
本文介绍了安卓:流媒体的相机MJPEG的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在搜索SO和谷歌我开始放弃了,所以我想我也可以在这里发表。几天

After several days of searching SO and google I'm beginning to give up, so I thought I might as well post here.

我创建一个Android应用程序,它应该提供某种形式的视频聊天。由于这应该是尽可能地接近,以实时,我也读到了各种协议,并决定尝试MJPEG对于初学者(不与音频有关目前如此)。

I'm creating an android app which should offer some kind of video chat. As this should be as close as possible to realtime, I read about various protocols and decided to try MJPEG for starters (not concerning with audio for now).

现在流的数据是推动我坚果。连接被建立,应用程序开始写相机preVIEW帧流,但既不VLC也不mplayer的开始播放视频。监视连接揭示该数据到达

Right now streaming the data is driving me nuts. The connection gets established, the app starts writing the camera preview frames to the stream, but neither VLC nor mplayer start playing video. Monitoring the connection reveals that the data is arriving.

连接 这code由一个异步任务执行,一个监听器成功通知:

Connecting This code is executed by an async task, a listener is notified on success:

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 和平板电脑注册一个连接(从而开始我的流光和相机preVIEW )。这也适用于VLC。

On my PC I execute 'mplayer http://tabletIP:8080' and the tablet registers a connection (and thus starts my streamer and the camera preview). This also works with 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.on previewFrame()回调触发:

Afterwards streaming is triggered through the Camera.onPreviewFrame() Callback:

@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的,都无济于事(顺便说一句,这是更好的?)。

There is no exception thrown. The mHandler runs in it's own HandlerThread. Just to be sure I tried using an AsyncTask, to no avail (btw, is this better?).

带连接codeD架的罚款对Android的一面,我将它们保存为JPG文件,可以打开它们。

The encoded frames are fine on the android side, I saved them to jpg files and could open them.

我的猜测是,我必须以某种方式聚集的数据,或者需要设置一些选项的插座什么的,但是....好,我坚持。

My guess is that I have to cluster the data somehow or have to set some options for the socket or something, but....well, I'm stuck.

TL;博士: VLC不打流时,MPlayer说,高速缓存未加注,问题很可能在最后code段,需要帮助〜:)

tl;dr: VLC not playing stream, mplayer says 'cache not filling', problem probably in last code segment, need help~ :)

感谢您了!

推荐答案

我知道了。看来,像我的基于HTTP /内容头被搞砸了。正确的标题应该是:

I got it. Seems, like my http-/content-headers were messed up. The proper headers should be:

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 \ñ一样的东西)...

Of course, where to put the boundary is your own choice. Also there are probably some fields which are optional (e.g. most in Cache-Control), but this works and till now I was too lazy to strip them down. The important part is to remember the linebreaks (\r\n thingies)...

这篇关于安卓:流媒体的相机MJPEG的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆