我正在尝试从自定义视频源对象流式传输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的请求定向到此处理程序,没有处理程序我可以看到它为什么不起作用。我有什么办法让这个处理程序来处理请求?
答案 0 :(得分: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.
}
其他人可能有不同的方法,可能使用其他我不知道的库,特别是multipartinputstream标题处理部分?
Multipart类实际上会自动处理每个Bodypart的标题部分,但它不适合流式传输。
快乐的编码。