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