ilabs-flir 2.4.11 → 2.4.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -64,6 +64,7 @@ object FlirManager {
|
|
|
64
64
|
|
|
65
65
|
fun setTextureCallback(callback: TextureUpdateCallback?) {
|
|
66
66
|
textureCallback = callback
|
|
67
|
+
sdkManager?.setFrameConsumerActive(callback != null)
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
interface TemperatureUpdateCallback {
|
|
@@ -107,6 +108,7 @@ object FlirManager {
|
|
|
107
108
|
sdkManager = FlirSdkManager.getInstance(context)
|
|
108
109
|
sdkManager?.setListener(sdkListener)
|
|
109
110
|
sdkManager?.initialize()
|
|
111
|
+
sdkManager?.setFrameConsumerActive(textureCallback != null)
|
|
110
112
|
|
|
111
113
|
isInitialized = true
|
|
112
114
|
Log.i(TAG, "FlirManager initialized")
|
|
@@ -56,6 +56,10 @@ public class FlirSdkManager {
|
|
|
56
56
|
private final List<Identity> discoveredDevices = Collections.synchronizedList(new ArrayList<>());
|
|
57
57
|
private final Map<String, DiscoveredCamera> discoveredCameras = Collections.synchronizedMap(new HashMap<>());
|
|
58
58
|
private volatile Bitmap latestBitmap;
|
|
59
|
+
private final Bitmap[] bitmapRingBuffer = new Bitmap[3];
|
|
60
|
+
private int ringBufferIndex = 0;
|
|
61
|
+
private volatile boolean isFrameConsumerActive = false;
|
|
62
|
+
private int[] scalePixelBuffer = null;
|
|
59
63
|
private volatile String currentPaletteName = "WhiteHot";
|
|
60
64
|
private final AtomicBoolean isProcessingFrame = new AtomicBoolean(false);
|
|
61
65
|
private boolean useHalfScale = false;
|
|
@@ -118,6 +122,22 @@ public class FlirSdkManager {
|
|
|
118
122
|
}
|
|
119
123
|
}
|
|
120
124
|
};
|
|
125
|
+
|
|
126
|
+
// Auto-detect low-end device to enable useHalfScale
|
|
127
|
+
try {
|
|
128
|
+
android.app.ActivityManager.MemoryInfo mi = new android.app.ActivityManager.MemoryInfo();
|
|
129
|
+
android.app.ActivityManager activityManager = (android.app.ActivityManager) this.context.getSystemService(Context.ACTIVITY_SERVICE);
|
|
130
|
+
if (activityManager != null) {
|
|
131
|
+
activityManager.getMemoryInfo(mi);
|
|
132
|
+
boolean isLowRam = activityManager.isLowRamDevice();
|
|
133
|
+
if (isLowRam || mi.totalMem < 3L * 1024 * 1024 * 1024) {
|
|
134
|
+
useHalfScale = true;
|
|
135
|
+
Log.i(TAG, "Low-end device detected (Total RAM: " + (mi.totalMem / (1024 * 1024)) + "MB). Enabling half-scale rendering by default.");
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
} catch (Throwable t) {
|
|
139
|
+
Log.e(TAG, "Failed to auto-detect memory constraints", t);
|
|
140
|
+
}
|
|
121
141
|
}
|
|
122
142
|
|
|
123
143
|
public static synchronized FlirSdkManager getInstance(Context context) {
|
|
@@ -145,6 +165,25 @@ public class FlirSdkManager {
|
|
|
145
165
|
try {
|
|
146
166
|
android.os.Looper.loop();
|
|
147
167
|
} catch (Throwable t) {
|
|
168
|
+
if (t instanceof VirtualMachineError) {
|
|
169
|
+
Log.e(TAG, "🚨 [FLIR LOOPER PROTECTOR] VirtualMachineError/OOM detected! Releasing display bitmap and running GC...");
|
|
170
|
+
try {
|
|
171
|
+
if (instance != null) {
|
|
172
|
+
synchronized (instance) {
|
|
173
|
+
for (int i = 0; i < 3; i++) {
|
|
174
|
+
if (instance.bitmapRingBuffer[i] != null) {
|
|
175
|
+
instance.bitmapRingBuffer[i].recycle();
|
|
176
|
+
instance.bitmapRingBuffer[i] = null;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
instance.latestBitmap = null;
|
|
180
|
+
instance.scalePixelBuffer = null;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
System.gc();
|
|
184
|
+
} catch (Throwable ignored) {}
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
148
187
|
String msg = t.getMessage();
|
|
149
188
|
boolean isSuppressed = false;
|
|
150
189
|
|
|
@@ -425,6 +464,11 @@ public class FlirSdkManager {
|
|
|
425
464
|
});
|
|
426
465
|
}
|
|
427
466
|
|
|
467
|
+
public void setFrameConsumerActive(boolean active) {
|
|
468
|
+
this.isFrameConsumerActive = active;
|
|
469
|
+
Log.d(TAG, "isFrameConsumerActive set to: " + active);
|
|
470
|
+
}
|
|
471
|
+
|
|
428
472
|
private void startStreamInternal() {
|
|
429
473
|
if (camera == null) {
|
|
430
474
|
notifyError("Not connected");
|
|
@@ -507,11 +551,13 @@ public class FlirSdkManager {
|
|
|
507
551
|
synchronized (FlirSdkManager.this) {
|
|
508
552
|
if (streamer != null && activeStream != null) {
|
|
509
553
|
streamer.update();
|
|
510
|
-
|
|
511
554
|
final String paletteToApply = currentPaletteName;
|
|
512
555
|
final String snapshotPath = pendingSnapshotPath;
|
|
513
556
|
pendingSnapshotPath = null;
|
|
514
557
|
streamer.withThermalImage(thermalImage -> {
|
|
558
|
+
if (!isFrameConsumerActive && snapshotPath == null) {
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
515
561
|
// 1. Apply Palette
|
|
516
562
|
if (paletteToApply != null) {
|
|
517
563
|
try {
|
|
@@ -584,22 +630,79 @@ public class FlirSdkManager {
|
|
|
584
630
|
}
|
|
585
631
|
|
|
586
632
|
// 3. Generate Bitmap for display
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
633
|
+
if (isFrameConsumerActive) {
|
|
634
|
+
try {
|
|
635
|
+
ImageBuffer imageBuffer = streamer.getImage();
|
|
636
|
+
if (imageBuffer != null) {
|
|
637
|
+
int width = imageBuffer.getWidth();
|
|
638
|
+
int height = imageBuffer.getHeight();
|
|
639
|
+
if (width > 0 && height > 0) {
|
|
640
|
+
synchronized (FlirSdkManager.this) {
|
|
641
|
+
int dstW = useHalfScale ? (width / 2) : width;
|
|
642
|
+
int dstH = useHalfScale ? (height / 2) : height;
|
|
643
|
+
|
|
644
|
+
for (int i = 0; i < 3; i++) {
|
|
645
|
+
if (bitmapRingBuffer[i] == null ||
|
|
646
|
+
bitmapRingBuffer[i].getWidth() != dstW ||
|
|
647
|
+
bitmapRingBuffer[i].getHeight() != dstH) {
|
|
648
|
+
|
|
649
|
+
if (bitmapRingBuffer[i] != null) {
|
|
650
|
+
bitmapRingBuffer[i].recycle();
|
|
651
|
+
}
|
|
652
|
+
bitmapRingBuffer[i] = Bitmap.createBitmap(dstW, dstH, Bitmap.Config.ARGB_8888);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
ringBufferIndex = (ringBufferIndex + 1) % 3;
|
|
656
|
+
Bitmap targetBitmap = bitmapRingBuffer[ringBufferIndex];
|
|
657
|
+
|
|
658
|
+
if (useHalfScale) {
|
|
659
|
+
imageBuffer.with(new com.flir.thermalsdk.utils.Consumer<java.nio.ByteBuffer>() {
|
|
660
|
+
@Override
|
|
661
|
+
public void accept(java.nio.ByteBuffer byteBuffer) {
|
|
662
|
+
if (byteBuffer != null) {
|
|
663
|
+
byteBuffer.rewind();
|
|
664
|
+
java.nio.IntBuffer srcPixels = byteBuffer.asIntBuffer();
|
|
665
|
+
|
|
666
|
+
int totalPixels = dstW * dstH;
|
|
667
|
+
if (scalePixelBuffer == null || scalePixelBuffer.length != totalPixels) {
|
|
668
|
+
scalePixelBuffer = new int[totalPixels];
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
for (int y = 0; y < dstH; y++) {
|
|
672
|
+
int srcY = y * 2;
|
|
673
|
+
int srcRowOffset = srcY * width;
|
|
674
|
+
int dstRowOffset = y * dstW;
|
|
675
|
+
for (int x = 0; x < dstW; x++) {
|
|
676
|
+
int srcX = x * 2;
|
|
677
|
+
scalePixelBuffer[dstRowOffset + x] = srcPixels.get(srcRowOffset + srcX);
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
targetBitmap.setPixels(scalePixelBuffer, 0, dstW, 0, 0, dstW, dstH);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
});
|
|
684
|
+
} else {
|
|
685
|
+
imageBuffer.with(new com.flir.thermalsdk.utils.Consumer<java.nio.ByteBuffer>() {
|
|
686
|
+
@Override
|
|
687
|
+
public void accept(java.nio.ByteBuffer byteBuffer) {
|
|
688
|
+
if (byteBuffer != null) {
|
|
689
|
+
byteBuffer.rewind();
|
|
690
|
+
targetBitmap.copyPixelsFromBuffer(byteBuffer);
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
latestBitmap = targetBitmap;
|
|
697
|
+
if (listener != null) {
|
|
698
|
+
listener.onFrame(targetBitmap);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
}
|
|
599
702
|
}
|
|
703
|
+
} catch (Exception e) {
|
|
704
|
+
Log.e(TAG, "Bitmap buffer copy failed", e);
|
|
600
705
|
}
|
|
601
|
-
} catch (Exception e) {
|
|
602
|
-
Log.e(TAG, "Bitmap creation failed", e);
|
|
603
706
|
}
|
|
604
707
|
});
|
|
605
708
|
}
|
|
@@ -641,7 +744,14 @@ public class FlirSdkManager {
|
|
|
641
744
|
activeStream = null;
|
|
642
745
|
}
|
|
643
746
|
streamer = null;
|
|
747
|
+
for (int i = 0; i < 3; i++) {
|
|
748
|
+
if (bitmapRingBuffer[i] != null) {
|
|
749
|
+
bitmapRingBuffer[i].recycle();
|
|
750
|
+
bitmapRingBuffer[i] = null;
|
|
751
|
+
}
|
|
752
|
+
}
|
|
644
753
|
latestBitmap = null;
|
|
754
|
+
scalePixelBuffer = null;
|
|
645
755
|
}
|
|
646
756
|
Log.d(TAG, "Streaming stopped");
|
|
647
757
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ilabs-flir",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.12",
|
|
4
4
|
"description": "FLIR Thermal SDK for React Native - iOS & Android (bundled at compile time via postinstall)",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"types": "src/index.d.ts",
|
|
@@ -67,4 +67,4 @@
|
|
|
67
67
|
"sourceDir": "./android/Flir"
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
|
-
}
|
|
70
|
+
}
|