--- /dev/null
+package net.osdn.gokigen.a01d.camera.fujix.wrapper.liveview
+
+import android.app.Activity
+import android.util.Log
+import androidx.preference.PreferenceManager
+import net.osdn.gokigen.a01d.camera.ILiveViewControl
+import net.osdn.gokigen.a01d.camera.fujix.wrapper.command.IFujiXCommunication
+import net.osdn.gokigen.a01d.camera.utils.SimpleLogDumper
+import net.osdn.gokigen.a01d.liveview.liveviewlistener.CameraLiveViewListenerImpl
+import net.osdn.gokigen.a01d.liveview.liveviewlistener.ILiveViewListener
+import net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor
+import java.net.Socket
+import java.util.*
+
+class FujiXLiveViewControl(activity: Activity, private val ipAddress: String, private val portNumber: Int) : ILiveViewControl, IFujiXCommunication
+{
+ private val TAG = toString()
+ private val liveViewListener = CameraLiveViewListenerImpl()
+ private var waitMs = 0
+ private var isStart = false
+ private val logcat = false
+ private val preferences = PreferenceManager.getDefaultSharedPreferences(activity)
+
+ init
+ {
+ try
+ {
+ val waitMsStr = preferences.getString(IPreferencePropertyAccessor.FUJIX_LIVEVIEW_WAIT, IPreferencePropertyAccessor.FUJIX_LIVEVIEW_WAIT_DEFAULT_VALUE)
+ logcat(" waitMS : $waitMsStr")
+ if (waitMsStr != null)
+ {
+ val wait = waitMsStr.toInt()
+ if (wait in 20 .. 800)
+ {
+ waitMs = wait
+ }
+ }
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ waitMs = 100
+ }
+ Log.v(TAG, " LOOP WAIT : $waitMs ms")
+ }
+
+ override fun startLiveView()
+ {
+ if (isStart)
+ {
+ // すでに受信スレッド動作中なので抜ける
+ Log.v(TAG, " LiveView IS ALREADY STARTED")
+ return
+ }
+ isStart = true
+ try
+ {
+ Thread {
+ try
+ {
+ startReceive(Socket(ipAddress, portNumber))
+ }
+ catch (e: Exception)
+ {
+ Log.v(TAG, " IP : $ipAddress port : $portNumber")
+ e.printStackTrace()
+ }
+ }.start()
+ }
+ catch (e : Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+ override fun stopLiveView()
+ {
+ isStart = false
+ }
+
+ override fun updateDigitalZoom()
+ {
+
+ }
+
+ override fun updateMagnifyingLiveViewScale(isChangeScale: Boolean)
+ {
+
+ }
+
+ override fun getMagnifyingLiveViewScale(): Float
+ {
+ return (1.0f)
+ }
+
+ override fun changeLiveViewSize(size: String)
+ {
+
+ }
+
+ override fun getDigitalZoomScale(): Float
+ {
+ return (1.0f)
+ }
+
+ fun getLiveViewListener(): ILiveViewListener
+ {
+ return (liveViewListener)
+ }
+
+ override fun connect(): Boolean
+ {
+ return (true)
+ }
+
+ override fun disconnect()
+ {
+ isStart = false
+ }
+
+ private fun logcat(message: String)
+ {
+ if (logcat)
+ {
+ Log.v(TAG, message)
+ }
+ }
+
+ private fun dump_bytes(header : String, byteArray: ByteArray, size : Int = 24)
+ {
+ if (logcat)
+ {
+ SimpleLogDumper.dump_bytes(header, byteArray.copyOf(size))
+ }
+ }
+
+ private fun startReceive(socket: Socket)
+ {
+ var errorCount = 0
+ val isr = socket.getInputStream()
+ val byteArray = ByteArray(BUFFER_SIZE + 32)
+
+ while (isStart)
+ {
+ try
+ {
+ var findJpeg = false
+ var length_bytes: Int
+ var read_bytes = isr.read(byteArray, 0, BUFFER_SIZE)
+ if (read_bytes > DATA_HEADER_OFFSET)
+ {
+ // メッセージボディの先頭にあるメッセージ長分は読み込む
+ length_bytes = (byteArray[3].toInt() and 0xff shl 24) + (byteArray[2].toInt() and 0xff shl 16) + (byteArray[1].toInt() and 0xff shl 8) + (byteArray[0].toInt() and 0xff)
+ if (byteArray[18] == 0xff.toByte() && byteArray[19] == 0xd8.toByte())
+ {
+ findJpeg = true
+ while (read_bytes < length_bytes && read_bytes < BUFFER_SIZE && length_bytes <= BUFFER_SIZE)
+ {
+ val append_bytes = isr.read(byteArray, read_bytes, length_bytes - read_bytes)
+ logcat("READ AGAIN : $append_bytes [$read_bytes]")
+ if (append_bytes < 0)
+ {
+ break
+ }
+ read_bytes = read_bytes + append_bytes
+ }
+ logcat("READ BYTES : " + read_bytes + " (" + length_bytes + " bytes, " + waitMs + "ms)")
+ }
+ else
+ {
+ // ウェイトを短めに入れてマーカーを拾うまで待つ
+ Thread.sleep(waitMs / 4.toLong())
+ logcat(" --- wait LiveView ---")
+ continue
+ }
+ }
+
+ // 先頭データをダンプする
+ dump_bytes("[LV]", byteArray)
+ if (findJpeg)
+ {
+ liveViewListener.onUpdateLiveView(Arrays.copyOfRange(byteArray, DATA_HEADER_OFFSET, read_bytes - DATA_HEADER_OFFSET), null)
+ errorCount = 0
+ }
+ Thread.sleep(waitMs.toLong())
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ errorCount++
+ }
+
+ if (errorCount > ERROR_LIMIT)
+ {
+ // エラーが連続でたくさん出たらループをストップ(ライブビューを停止)させる
+ isStart = false
+ }
+ }
+
+ try
+ {
+ isr.close()
+ socket.close()
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+ private fun startReceiveAlter(socket: Socket)
+ {
+ var errorCount = 0
+ val isr = socket.getInputStream()
+ val byteArray = ByteArray(BUFFER_SIZE + 32)
+
+ while (isStart)
+ {
+ try
+ {
+ var findJpeg = false
+ var length_bytes: Int
+ var read_bytes = isr.read(byteArray, 0, BUFFER_SIZE)
+
+ // 先頭データ(48バイト分)をダンプ
+ // dump_bytes("[lv]", byteArray, 48)
+ if (read_bytes > DATA_HEADER_OFFSET)
+ {
+ // メッセージボディの先頭にあるメッセージ長分は読み込む
+ length_bytes = (byteArray[3].toInt() and 0xff shl 24) + (byteArray[2].toInt() and 0xff shl 16) + (byteArray[1].toInt() and 0xff shl 8) + (byteArray[0].toInt() and 0xff)
+ if (byteArray[18] == 0xff.toByte() && byteArray[19] == 0xd8.toByte())
+ {
+ findJpeg = true
+ while (read_bytes < length_bytes && read_bytes < BUFFER_SIZE && length_bytes <= BUFFER_SIZE)
+ {
+ val append_bytes = isr.read(byteArray, read_bytes, length_bytes - read_bytes)
+ logcat("READ AGAIN : $append_bytes [$read_bytes]")
+ if (append_bytes < 0)
+ {
+ break
+ }
+ read_bytes = read_bytes + append_bytes
+ }
+ logcat("READ BYTES : " + read_bytes + " (" + length_bytes + " bytes, " + waitMs + "ms)")
+ }
+ else
+ {
+ // ウェイトを短めに入れてマーカーを拾うまで待つ
+ Thread.sleep(waitMs / 4.toLong())
+ logcat(" --- wait LiveView ---")
+ continue
+ }
+ }
+
+ // 先頭データをダンプする
+ dump_bytes("[LV]", byteArray)
+ if (findJpeg)
+ {
+ liveViewListener.onUpdateLiveView(Arrays.copyOfRange(byteArray, DATA_HEADER_OFFSET, read_bytes - DATA_HEADER_OFFSET), null)
+ errorCount = 0
+ }
+ Thread.sleep(waitMs.toLong())
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ errorCount++
+ }
+
+ if (errorCount > ERROR_LIMIT)
+ {
+ // エラーが連続でたくさん出たらループをストップ(ライブビューを停止)させる
+ isStart = false
+ }
+ }
+
+ try
+ {
+ isr.close()
+ socket.close()
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+
+ companion object
+ {
+ private const val DATA_HEADER_OFFSET = 18
+ private const val BUFFER_SIZE = 2048 * 1280
+ private const val ERROR_LIMIT = 30
+ }
+}
import static net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.FUJIX_LIVEVIEW_WAIT_DEFAULT_VALUE;
-public class FujiXLiveViewControl implements ILiveViewControl, IFujiXCommunication
+public class FujiXLiveViewControlAlternate implements ILiveViewControl, IFujiXCommunication
{
private final String TAG = toString();
private final String ipAddress;
private static final int BUFFER_SIZE = 2048 * 1280;
private static final int ERROR_LIMIT = 30;
private boolean isStart = false;
- private boolean logcat = false;
+ private boolean logcat = true;
- public FujiXLiveViewControl(@NonNull Activity activity, String ip, int portNumber)
+ public FujiXLiveViewControlAlternate(@NonNull Activity activity, String ip, int portNumber)
{
this.ipAddress = ip;
this.portNumber = portNumber;
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
String waitMsStr = preferences.getString(FUJIX_LIVEVIEW_WAIT, FUJIX_LIVEVIEW_WAIT_DEFAULT_VALUE);
logcat("waitMS : " + waitMsStr);
- int wait = Integer.parseInt(waitMsStr);
- if ((wait >= 20)&&(wait <= 800))
+ if (waitMsStr != null)
{
- waitMs = wait;
+ int wait = Integer.parseInt(waitMsStr);
+ if ((wait >= 20) && (wait <= 800))
+ {
+ waitMs = wait;
+ }
}
}
catch (Exception e)
if (isStart)
{
// すでに受信スレッド動作中なので抜ける
+ Log.v(TAG, " LiveView IS ALREADY STARTED");
return;
}
isStart = true;
boolean findJpeg = false;
int length_bytes;
int read_bytes = isr.read(byteArray, 0, BUFFER_SIZE);
+
+ // 先頭データ(48バイト分)をダンプ
+ dump_bytes("[lv]", byteArray, 48);
+
if (read_bytes > DATA_HEADER_OFFSET)
{
// メッセージボディの先頭にあるメッセージ長分は読み込む
{
// ウェイトを短めに入れてマーカーを拾うまで待つ
Thread.sleep(waitMs/4);
+ logcat(" --- wait LiveView ---");
continue;
}
}