如何从JavaHttpServer流式传输M-JPEG?
我试图从自定义视频源对象流式传输M-JPEG内容,但在查看wireshark的连接时,没有从服务器返回任何数据。下面是我使用的一些相关代码段。有人知道如何让这个代码运行吗 部分:如何从JavaHttpServer流式传输M-JPEG?,java,http,mjpeg,Java,Http,Mjpeg,我试图从自定义视频源对象流式传输M-JPEG内容,但在查看wireshark的连接时,没有从服务器返回任何数据。下面是我使用的一些相关代码段。有人知道如何让这个代码运行吗 部分: try { server = new HTTPServerWrapper(8099); server.MJpegBindVideoSource(camera, "/test");
try {
server = new HTTPServerWrapper(8099);
server.MJpegBindVideoSource(camera, "/test");
} catch (IOException ex) {
Logger.getLogger(Recorder.class.getName()).log(Level.SEVERE, null, ex);
}
physics/server/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));
}
}
physics/server/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();
}
}
};
编辑:在将connect消息添加到stderr之后,对http://192.168.2.7:8099/test的请求似乎没有被定向到此处理程序,因为没有处理程序,我可以理解为什么它不起作用。让这个处理程序来处理请求,我缺少了什么?我看到这个问题已经问了两年了,但我还是会发布我的答案,以防人们在这里搜索和找到。。。我是这样做的
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.
}
公共静态整型搜索(字节[]数组,字节[]子数组){
if(subArray.length>array.length)
返回-1;
int p=(新字符串(数组)).indexOf(新字符串(子数组));
对于(int i=1;iarray.length)
返回-1;
int p=(新字符串(数组)).indexOf(新字符串(子数组),关闭);
对于(int i=1;i.length());
System.out.println(“入站:+入站”);
int cli=con.getContentLength();
byte[]boundery=inbound.getBytes();
byte[]buffer=新字节[1024];//如果需要,请调整
int字节读取;
in=con.getInputStream();
MultiPartOutputStream MultiPartOutputStream=新的MultiPartOutputStream(扩展流);
String bounderyS=multiPartOutputStream.getBoundary();
addHeader(“传输编码”,null);
addHeader(“到期”、“0”);
addHeader(“Pragma”,“无缓存”);
addHeader(“访问控制允许来源”,“*”);
addHeader(“内容类型”,“多部分/x-mixed-replace;边界=”+bounderyS);
MultipartInputStream MultipartInputStream=新的MultipartInputStream(in,boundery);
布尔值boundstart=true;
while(multipartInputStream.nextInputStream()){
boundstart=true;
而((bytesRead=multipartInputStream.read(buffer))!=-1)
{
如果(开始){
字节[]tmpba=新字节[1024];
String searchString=“内容长度:”;
int clstart=searchFor(缓冲区,searchString.getBytes());
clstart+=searchString.getBytes().length;
int-clend=searchFor(缓冲区“\r\n”.getBytes(),clstart);
String conlen=新字符串(Arrays.copyOfRange(buffer、clstart、clend));
字符串[]头=新字符串[2];
标头[0]=“访问控制允许来源:”;
标题[1]=“内容长度:”+conlen;
multiPartOutputStream.startPart(“图像/jpeg”,标题);
buffer=Arrays.copyOfRange(buffer,clend+“\r\n\r\n”.getBytes().length,buffer.length);
bytesRead=buffer.length;
}
multiPartOutputStream.write(缓冲区,0,字节读取);
boundstart=false;
缓冲区=新字节[1024];
}
multiPartOutputStream.flush();
}
}捕获(IOE异常){
e、 printStackTrace();
}最后{
试一试{
in.close();
}捕获(IOE异常){
e、 printStackTrace();
}
con.disconnect();
试一试{
exptream.close();
}捕获(IOE异常){
e、 printStackTrace();
}
}
host=null;
link=null;
返回Response.ok(outstream,MultiPartMediaTypes.MULTIPART_MIXED_TYPE).build();//实际上您在这里给出什么并不重要,因为代码永远不会到达这里。
}
其他人可能有不同的方法,可能使用我不知道的其他库,特别是多部分InputStream头处理部分?
Multipart类实际上会自动处理其每个Bodypart的头部分,但就目前所知,它不适合流式处理
快乐的编码。PSSH。。。“requestHeaders”不代表响应头。对于残余,你到底为什么要使用
while(true)
infinite循环?@BalusC,现在这很尴尬。。。但是谢谢你的帮助。无限循环是暂时的,直到我可以植入一些代码来跟踪连接状态。测试修复后的代码后,我会继续跟进。@BalusC,我仍然有同样的问题。我已经将问题缩小到没有调用处理程序这一事实。连接正在建立,所以我不知道为什么不调用处理程序来请求“GET/test HTTP/1.1”@BalusC,问题现在解决了。我从未给HttpServer.start()我打过电话