package com.github.kmkt.util.mjpeg; import java.nio.ByteBuffer; public class FrameParser { private final ByteBuffer buffer; private int search_pos = 0; private int soi_pos = -1; public FrameParser(int bufsize) { buffer = ByteBuffer.allocateDirect(bufsize); } public FrameParser(ByteBuffer buffer) { if (buffer == null) throw new IllegalArgumentException("buffer should not be null"); this.buffer = buffer; } public ByteBuffer getByteBuffer() { return buffer; } /** * JPEG frame 抽出 * @return バッファに JPEG frame が含まれる場合はそのbyte配列 含まれない場合は null */ public byte[] getFrame() { // SOI 未検出 if (soi_pos < 0) { // SOI (0xFFD8) 検索 byte b0 = 0; byte b1 = 0; while (search_pos < buffer.position() - 1) { b0 = buffer.get(search_pos); b1 = buffer.get(search_pos+1); // simple search if (b0 == (byte) 0xff && b1 == (byte) 0xd8) { // hit buffer.limit(buffer.position()); buffer.position(search_pos); buffer.compact(); search_pos = 2; soi_pos = 0; break; } else { search_pos++; continue; } } } if (soi_pos < 0) { // SOI 未検出 buffer.limit(buffer.position()); buffer.position(search_pos); buffer.compact(); search_pos = 0; return null; } if (0 <= soi_pos) { // EOI (0xFFD9) 検索 byte b0 = 0; byte b1 = 0; while (search_pos < buffer.position() - 1) { b0 = buffer.get(search_pos); b1 = buffer.get(search_pos+1); // simple search if (b0 == (byte) 0xff && b1 == (byte) 0xd9) { // hit // SOI有り, EOI有り -> frame 抽出 int length = search_pos + 2 - soi_pos; byte[] frame = new byte[length]; // frame 抽出 int pos = buffer.position(); // 書き込み位置保存 buffer.position(soi_pos); buffer.limit(search_pos + 2); buffer.get(frame); soi_pos = -1; buffer.limit(pos); buffer.position(search_pos + 2); buffer.compact(); search_pos = 0; return frame; } else { search_pos++; continue; } } } // SOI有り, EOI未検出 return null; } // for debug protected int getSearchPos() { return search_pos; } protected int getSOIPos() { return soi_pos; } }