2013-04-26 2 views
1

Я пытаюсь передать поток M-JPEG из пользовательского объекта источника видео, но при просмотре соединения из wirehark данные не возвращаются с сервера. Ниже приведены некоторые соответствующие сегменты кода, которые я использовал. Кто-нибудь знает, как заставить этот код функционировать?Как вы можете передавать M-JPEG с Java HttpServer?

Сегмент:

  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(); 
     } 

    } 
}; 

Edit: После добавления сообщения о подключении to stderr кажется, что запросы на http: // 192.168.2.7:8099/test не направляются на этот обработчик, без обработчик, я вижу, почему он не работает. Что мне не хватает, чтобы обработать этот обработчик?

+0

Psssh ... "requestHeaders" не представляет заголовки ответов. Для остатка, почему именно вы используете бесконечный цикл 'while (true)? – BalusC

+0

@BalusC, теперь это смущает ... но спасибо за улов. Бесконечный цикл является временным, пока я не смогу внедрить некоторый код для отслеживания состояния соединения. Я буду следить после проверки кода. –

+0

@BalusC, у меня все еще такая же проблема. Я сузил проблему до того, что обработчик не вызван. Соединение устанавливается, поэтому я не знаю, почему обработчик не вызывается для запросов «GET/test HTTP/1.1» –

ответ

2

Я вижу, что прошло 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. 
} 

другие могут иметь различные aproaches, от, возможно, с помощью других библиотек, которые я не знаю, aspecially multipartinputstream заголовок обработки часть? Класс Multipart фактически автоматически обрабатывает часть заголовка каждого из своих Bodypart, но не подходит для потоковой передачи, насколько это возможно.

счастливы кодирования.