Телефон Android как видеосервер MJPEG в реальном времени

Я пытаюсь использовать свой телефон в качестве источника видео MJPEG в реальном времени. Пока что захват кадров и преобразование их в JPEG не представляет большого труда. Моя настоящая проблема - правильно отправить составной ответ. Существует множество документации об отправке составных ответов, но проблема с ними в том, что все они ожидают, что все изображения будут доступны в момент поступления HTTP-запроса (например, который будет использоваться для загрузки нескольких изображений). Конечно, для потоковой передачи в реальном времени мне нужно иметь возможность начать отправлять многостраничный ответ, постоянно добавляя jpeg-файлы в тело. Я ни в коем случае не фанат HTTP, поэтому мне нежелательно, чтобы от меня требовали откатывать свой собственный HTTP-ответ и писать напрямую в сокет. Есть ли библиотека, поддерживающая такое поведение? Я поискал в Интернете решения, но не нашел там ничего полезного.

Любые идеи? В худшем случае я был бы готов взглянуть на понятную человеку документацию о том, как написать составной ответ вручную, но я бы предпочел использовать библиотеку, если это возможно.

Заранее спасибо.

изменить: он работал с использованием библиотеки сервлетов orielly в соответствии с предложением сигмавируса. Обратите внимание, что поток MJPEG более или менее неявно выводится из того факта, что я отправляю multipart / x-mixed-replace, в котором есть только изображение / jpeg. Ознакомьтесь с комментарием в моем коде к руководству, в котором показано, какие библиотеки пристаней вам понадобятся для этого. Конечно, вам дополнительно понадобится cos.jar, библиотека сервлетов Orielly. Код следующий:

package edu.stevens.arpac.webclient;

import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Collections;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.http.conn.util.InetAddressUtils;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.Request;

import com.oreilly.servlet.MultipartResponse;
import com.oreilly.servlet.ServletUtils;


import android.os.Environment;
import android.util.Log;
// holla at http://puregeekjoy.blogspot.com/2011/06/running-embedded-jetty-in-android-app.html
public class JettyServer extends Thread 
{
private static final String TAG = "JettyServer";
private Server webServer;
private Boolean isStarted = false;

public JettyServer()
{
    super();
    Log.i(TAG, "Initializing server to port 8080");
    webServer = new Server(8080);

    Handler handler = new AbstractHandler() {
        public void handle(String target, Request request, HttpServletRequest servletRequest,
                HttpServletResponse servletResponse) throws IOException, ServletException {

            ServletOutputStream out = servletResponse.getOutputStream();

             MultipartResponse multi = new MultipartResponse(servletResponse);


             Boolean go = true;
             while( go )
             {

                 try
                 {
                     multi.startResponse("image/jpeg");
                     ServletUtils.returnFile(Environment.getExternalStorageDirectory().getPath() + "/ARPac/twi.jpg", out);
                     multi.endResponse();
                 }
                 catch(IOException ex)
                 {
                    go = false;
                    Log.i(TAG, "IO Failed with exception " + ex.getMessage());
                 }
             }
             request.setHandled(true);
        }
    };
    webServer.setHandler(handler);

    try {
        webServer.start();
        Log.d(TAG, "started Web server @ " + getIPAddress());
        isStarted = true;

    }
    catch (Exception e) {
        Log.d(TAG, "unexpected exception starting Web server: " + e);
    }
}

/**
 * Get IP address from first non-localhost interface
 * @return  address or empty string
 */
private String getIPAddress() 
{
    try 
    {
        List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
        for (NetworkInterface intf : interfaces) 
        {
            List<InetAddress> addrs = Collections.list(intf.getInetAddresses());
            for (InetAddress addr : addrs) 
            {
                if (!addr.isLoopbackAddress())
                {
                    String sAddr = addr.getHostAddress().toUpperCase(); 
                    if (InetAddressUtils.isIPv4Address(sAddr))
                    {
                        //Log.d(TAG, "IP address is: " + sAddr);
                        return sAddr;
                    } 
                }
            }
        }
    } 
    catch (Exception ex) 
    { 
        Log.e(TAG, "could not get IP address: " + ex.getMessage());
    } // for now eat exceptions
    Log.e(TAG, "Could not find a non-loopback IPv4 address!");
    return "";
}

public void teardown()
{
    if( isStarted )
    {
        try {
            webServer.stop();
            isStarted = false;
        } catch (Exception e) {
            Log.e(TAG, "Couldn't stop server. Probably was called when server already stopped.");
        }
    }
}

public void run() 
 {

 }

}


person mercurytw    schedule 08.01.2013    source источник
comment
Извините за то, что мой класс JettyServer расширяет Thread, но ничего с ним не делает. Вам не нужно этого делать. Это просто направление, в котором движется мой код.   -  person mercurytw    schedule 10.01.2013


Ответы (1)


Вы видели это? http://www.servlets.com/cos/javadoc/com/oreilly/servlet/MultipartResponse.html Похоже, что в этом примере каждая часть отправляется отдельно и ожидает определенный временной лимит перед отправкой следующей или получением прерывания.

person Ian Stapleton Cordasco    schedule 09.01.2013
comment
вы знаете, я помню, как наткнулся на это. Эта библиотека зависит от некоторых других библиотек, которых нет в Android, поэтому я не стал ее преследовать. Думаю, я сделаю еще один шанс, потому что он действительно делает то, что мне нужно. - person mercurytw; 09.01.2013
comment
Как я уже сказал, если вы разместите его на @ quora, я позабочусь о том, чтобы его увидели более 200 человек. У них там может быть какое-то понимание. - person Ian Stapleton Cordasco; 09.01.2013