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;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 start(); } <span class="synType">private</span> <span class="synType">boolean</span> stop = <span class="synConstant">true</span>; <span class="synType">public</span> <span class="synType">void</span> stop(){ stop = <span class="synConstant">true</span>; } <span class="synType">public</span> <span class="synType">boolean</span> start(){ <span class="synStatement">if</span>(!stop){ <span class="synStatement">return</span> <span class="synConstant">false</span>; } stop = <span class="synConstant">false</span>; <span class="synStatement">new</span> Thread(){ <span class="synPreProc">@Override</span> <span class="synType">public</span> <span class="synType">void</span> run(){ <span class="synStatement">try</span> { read(); } <span class="synStatement">catch</span> (IOException ex) { Logger.getLogger(HttpChankedReader.<span class="synType">class</span>.getName()).log(Level.SEVERE, <span class="synConstant">null</span>, ex); } } }.start(); <span class="synStatement">return</span> !stop; } <span class="synType">public</span> <span class="synType">boolean</span> isStop(){ <span class="synStatement">return</span> stop; } <span class="synType">private</span> <span class="synType">final</span> <span class="synType">void</span> read() <span class="synType">throws</span> IOException { ByteArrayOutputStream bytes = <span class="synStatement">new</span> ByteArrayOutputStream(); HttpURLConnection con = (HttpURLConnection) url.openConnection(); System.out.println(con.getHeaderField(<span class="synConstant">"Content-Type"</span>)); <span class="synStatement">try</span> (InputStream in = con.getInputStream()) { BufferedInputStream bin = <span class="synStatement">new</span> BufferedInputStream(in); <span class="synType">int</span> contentLength = -<span class="synConstant">1</span>; <span class="synType">int</span> cnt = <span class="synConstant">0</span>; <span class="synType">byte</span>[] buff = <span class="synStatement">new</span> <span class="synType">byte</span>[<span class="synConstant">1024</span>]; <span class="synStatement">while</span> ((cnt = bin.read(buff, <span class="synConstant">0</span>, buff.length)) != -<span class="synConstant">1</span> && !stop) { bytes.write(buff, <span class="synConstant">0</span>, cnt); <span class="synStatement">if</span> (contentLength < <span class="synConstant">0</span>) { <span class="synStatement">if</span>(<span class="synStatement">new</span> String(bytes.toByteArray()).startsWith(<span class="synConstant">"--Boundary"</span>)){ <span class="synType">int</span> start = <span class="synStatement">new</span> String(bytes.toByteArray()).indexOf(<span class="synConstant">"</span><span class="synSpecial">\r\n\r\n</span><span class="synConstant">"</span>); <span class="synStatement">if</span> (start != -<span class="synConstant">1</span>) { <span class="synComment">//System.out.println("------------- Hit! --------------- " + start);</span> contentLength = getContextLength(<span class="synStatement">new</span> String(bytes.toByteArray(), <span class="synConstant">0</span>, start)) - bytes.size(); } }<span class="synStatement">else</span>{ <span class="synComment">//System.out.println("NG[no start with --Boundary] " + (char)bytes.toByteArray()[0]);</span> <span class="synComment">//読み直し</span> <span class="synType">int</span> idx = <span class="synStatement">new</span> String(bytes.toByteArray()).indexOf(<span class="synConstant">"--Boundary"</span>); <span class="synStatement">if</span>(idx != -<span class="synConstant">1</span>){ <span class="synType">byte</span>[] buf = bytes.toByteArray(); bytes.reset(); bytes.write(buf, idx, buf.length - idx); <span class="synComment">//System.out.println("読み直し shift idx >> " + idx + " " + (char)bytes.toByteArray()[0]);</span> } contentLength = -<span class="synConstant">1</span>; } } <span class="synStatement">else</span> { contentLength -= cnt; <span class="synStatement">if</span> (contentLength < <span class="synConstant">0</span>) { <span class="synType">synchronized</span>(<span class="synType">this</span>){ <span class="synType">int</span> start = <span class="synStatement">new</span> String(bytes.toByteArray()).indexOf(<span class="synConstant">"</span><span class="synSpecial">\r\n\r\n</span><span class="synConstant">"</span>);//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(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <span class="synType">private</span> <span class="synType">static</span> <span class="synType">int</span> getContextLength(String header) { <span class="synType">int</span> ret = -<span class="synConstant">1</span>; <span class="synStatement">for</span> (String line : header.split(<span class="synConstant">"</span><span class="synSpecial">\n</span><span class="synConstant">"</span>)) { <span class="synStatement">if</span> (line.toUpperCase().trim().startsWith(<span class="synConstant">"CONTENT-LENGTH:"</span>)) { <span class="synStatement">try</span>{ ret = Integer.parseInt(line.substring(line.lastIndexOf(<span class="synConstant">":"</span>) + <span class="synConstant">1</span>).trim()); }<span class="synStatement">catch</span>(Exception err){ <span class="synComment">//No Check.</span> } } } <span class="synStatement">return</span> ret; } <span class="synType">abstract</span> <span class="synType">void</span> readChankBytes(<span class="synType">byte</span>[] data);}
moremagic
2014-09-17