Linux motion のJavaビューア作成
Linux Motion でストリーミング配信している画像を
Firefoxで見てたら、ブラウザが固まってしまうことが多かったのです。
Javaのビューワを探してみたら cambozola.jar っていうアプレットがあるようです。
アプレットは嫌だなぁ。ってことでswingで作ってみました。
HTTP ストリームを実際に読み込んでいる部分のソースはこんな感じです。
※画像の右下端が少し壊れちゃうバグがあるけど何とか見れます。
※画像の右下端が乱れる不具合を修正しました
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package motionframe; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.Arrays; import java.util.logging.Level; import java.util.logging.Logger; /** * * @author moremagic */ public abstract class HttpChankedReader{ private URL url = null; public HttpChankedReader(String sUrl) throws MalformedURLException{ this(new URL(sUrl)); } public HttpChankedReader(URL url){ this.url = url; start(); } private boolean stop = true; public void stop(){ stop = true; } public boolean start(){ if(!stop){ return false; } stop = false; new Thread(){ @Override public void run(){ try { read(); } catch (IOException ex) { Logger.getLogger(HttpChankedReader.class.getName()).log(Level.SEVERE, null, ex); } } }.start(); return !stop; } public boolean isStop(){ return stop; } private final void read() throws IOException { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); HttpURLConnection con = (HttpURLConnection) url.openConnection(); System.out.println(con.getHeaderField("Content-Type")); try (InputStream in = con.getInputStream()) { BufferedInputStream bin = new BufferedInputStream(in); int contentLength = -1; int cnt = 0; byte[] buff = new byte[1024]; while ((cnt = bin.read(buff, 0, buff.length)) != -1 && !stop) { bytes.write(buff, 0, cnt); if (contentLength < 0) { if(new String(bytes.toByteArray()).startsWith("--Boundary")){ int start = new String(bytes.toByteArray()).indexOf("\r\n\r\n"); if (start != -1) { //System.out.println("------------- Hit! --------------- " + start); contentLength = getContextLength(new String(bytes.toByteArray(), 0, start)) - bytes.size(); } }else{ //System.out.println("NG[no start with --Boundary] " + (char)bytes.toByteArray()[0]); //読み直し int idx = new String(bytes.toByteArray()).indexOf("--Boundary"); if(idx != -1){ byte[] buf = bytes.toByteArray(); bytes.reset(); bytes.write(buf, idx, buf.length - idx); //System.out.println("読み直し shift idx >> " + idx + " " + (char)bytes.toByteArray()[0]); } contentLength = -1; } } else { contentLength -= cnt; if (contentLength < 0) { synchronized(this){ int start = new String(bytes.toByteArray()).indexOf("\r\n\r\n"); //Length 分のデータだけでは右下画像が欠けるため、Length+1 //readChankBytes(Arrays.copyOfRange(bytes.toByteArray(), start + 4 , bytes.size() - (start + 4))); byte[] data = Arrays.copyOfRange(bytes.toByteArray(), start + 4, getContextLength(new String(bytes.toByteArray(), 0 , start) + 1)); readChankBytes(data); } bytes.reset(); } } } } catch (IOException err) { err.printStackTrace(); } } private static int getContextLength(String header) { int ret = -1; for (String line : header.split("\n")) { if (line.toUpperCase().trim().startsWith("CONTENT-LENGTH:")) { try{ ret = Integer.parseInt(line.substring(line.lastIndexOf(":") + 1).trim()); }catch(Exception err){ //No Check. } } } return ret; } abstract void readChankBytes(byte[] data); }