簡體   English   中英

如何從Java HttpServer流式傳輸M-JPEG?

[英]How can you stream M-JPEG from a Java HttpServer?

我正在嘗試從自定義視頻源對象流式傳輸M-JPEG內容,但是在查看Wireshark的連接時,服務器未返回任何數據。 以下是我使用的一些相關代碼段。 有誰知道如何使此代碼起作用?

分割:

            try {
                server = new HTTPServerWrapper(8099);                
                server.MJpegBindVideoSource(camera, "/test");
            } catch (IOException ex) {
                Logger.getLogger(Recorder.class.getName()).log(Level.SEVERE, null, ex);
            }

物理/服務器/ HTTPServerWrapper.java:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package physics.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import physics.VideoSource;

/**
 *
 * @author rritoch
 */
public class HTTPServerWrapper  {

    com.sun.net.httpserver.HttpServer server;

    public HTTPServerWrapper(int port) throws IOException{        
       server = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(port), 0);                
    }

    public void MJpegBindVideoSource(VideoSource vs, String path) {        
        final VideoSource v = vs;        
        server.createContext(path,new MJpegHandler(vs)); 
    }    


}

物理/服務器/ MJpegHandler.java:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package physics.server;

import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.imageio.ImageIO;
import physics.VideoSource;

/**
 *
 * @author rritoch
 */
public class MJpegHandler implements HttpHandler {

    VideoSource vs;

    public MJpegHandler(VideoSource videosource) {
        this.vs = videosource;
    }

    public void setVideoSource(VideoSource videosource) {
        this.vs = videosource;
    }

    public void handle(HttpExchange connection) throws IOException {
        byte[] data;

        System.err.println("Connect...");

        String boundary = "VNetPhysics";

        Headers responseHeaders = connection.getResponseHeaders();
        responseHeaders.add("Content-Type", String.format("multipart/x-mixed-replace; boundary=--%s", boundary));
        responseHeaders.add("Cache-Control", "no-cache, private");
        responseHeaders.add("Pragma", "no-cache");
        responseHeaders.add("Max-Age", "0");
        responseHeaders.add("Expires", "0");
        connection.sendResponseHeaders(200, 0);
        OutputStream responseBody = connection.getResponseBody();



        while (true) {

            BufferedImage bufferedImage = vs.getBufferedImage();

            ByteArrayOutputStream os = new ByteArrayOutputStream(8192 * 4);
            ImageIO.write(bufferedImage, "jpg", os);
            data = os.toByteArray();
            os.close();


            responseBody.write(("--" + boundary + "\r\n"
                    + "Content-type: image/jpg\r\n"
                    + "Content-Length: "
                    + data.length
                    + "\r\n\r\n").getBytes());

            responseBody.write(data);
            responseBody.flush();
        }

    }
};

編輯:將連接消息添加到stderr后,似乎對http:// 192.168.2.7:8099/test的請求沒有被定向到此處理程序,沒有處理程序,我可以看到為什么它不起作用。 我缺少讓該處理程序處理請求的內容嗎?

我看到距提出此問題已有2年了,但無論如何我都會張貼答案,以防有人在這里搜索和發現……這是我的工作方式;

import org.mortbay.util.MultiPartOutputStream;
import org.w3c.www.mime.MultipartInputStream;

//其他的東西

public static int searchFor(byte[] array, byte[] subArray) {
    if (subArray.length > array.length)
        return -1;
    int p = (new String(array)).indexOf(new String(subArray));
    for (int i = 1; i < subArray.length; i++) {
        if (array[p + i] != subArray[i])
            return -1;
    }
    return p;
}

public static int searchFor(byte[] array, byte[] subArray, int off) {
    if (subArray.length > array.length)
        return -1;
    int p = (new String(array)).indexOf(new String(subArray), off);
    for (int i = 1; i < subArray.length; i++) {
        if (array[p + i] != subArray[i])
            return -1;
    }
    return p;
}

@GET
@Path("getcamlistfromip")
@Produces("multipart/image")
public Response getcamlist(@Context UriInfo info, @Context HttpServletResponse response){
    String host = "192.168.1.155:8080";
    String link = "mjpeg1";
    HttpURLConnection con = null;
    InputStream in = null;
    OutputStream outstream = null;
    final String fullURL = "http://" + host + "/" + link;

    try {

        outstream = response.getOutputStream();

        URL url = new URL(fullURL);
        con = (HttpURLConnection) url.openConnection();
        con.setConnectTimeout(35000);
        con.setReadTimeout(35000);
        int rc = con.getResponseCode();
        String ct = con.getHeaderField("Content-Type");
        int inbounds = ct.indexOf("boundary=--");
        String inbound = ct.substring(inbounds + "boundary=--".length());
        System.out.println("inbound: " + inbound);
        int cli = con.getContentLength();
        byte[] boundery = inbound.getBytes();
        byte[] buffer = new byte[1024]; // Adjust if you want
        int bytesRead;
        in = con.getInputStream();
        MultiPartOutputStream multiPartOutputStream = new MultiPartOutputStream(outstream);
        String bounderyS = multiPartOutputStream.getBoundary();
        response.addHeader("Transfer-Encoding", null);
        response.addHeader("Expires", "0");
        response.addHeader("Pragma", "no-cache");
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Content-Type", "multipart/x-mixed-replace;boundary=--"+bounderyS);
        MultipartInputStream multipartInputStream = new MultipartInputStream(in, boundery);

        boolean boundstart = true;
        while (multipartInputStream.nextInputStream()) {

            boundstart = true;
            while ((bytesRead = multipartInputStream.read(buffer)) != -1)
            {
                if (boundstart) {
                    byte[] tmpba = new byte[1024];

                    String searchString = "Content-Length: ";
                    int clstart = searchFor(buffer, searchString.getBytes());
                    clstart += searchString.getBytes().length;
                    int clend = searchFor(buffer, "\r\n".getBytes(), clstart);
                    String conlen = new String(Arrays.copyOfRange(buffer, clstart, clend));
                    String[] headers = new String[2];
                    headers[0] = "Access-Control-Allow-Origin: *";
                    headers[1] = "Content-length: " + conlen;
                    multiPartOutputStream.startPart("image/jpeg", headers);
                    buffer = Arrays.copyOfRange(buffer, clend + "\r\n\r\n".getBytes().length, buffer.length);

                    bytesRead = buffer.length;
                }
                multiPartOutputStream.write(buffer, 0, bytesRead);
                boundstart = false;
                buffer = new byte[1024];
            }
            multiPartOutputStream.flush();

        }

    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        con.disconnect();
        try {
            outstream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    host = null;
    link = null;

    return Response.ok(outstream, MultiPartMediaTypes.MULTIPART_MIXED_TYPE).build();//it actually doesn't matter what you give here since code never reaches here.
}

其他人可能有不同的方法,也許是通過使用我不知道的其他庫,特別是multipartinputstream標頭處理部分? 實際上,Multipart類確實會自動處理其Bodypart的每個標頭部分,但就其所知,它不適合流式傳輸。

快樂的編碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM