24
24
package com .github .serivesmejia .eocvsim .input .source ;
25
25
26
26
import com .github .serivesmejia .eocvsim .input .InputSource ;
27
+ import com .github .serivesmejia .eocvsim .input .InputSourceInitializer ;
27
28
import com .google .gson .annotations .Expose ;
28
29
import io .github .deltacv .papervision .plugin .ipc .stream .MjpegHttpReader ;
29
30
import org .opencv .core .Mat ;
@@ -86,11 +87,20 @@ public boolean init() {
86
87
return mjpegHttpReader != null && iterator != null ;
87
88
}
88
89
90
+ byte [] frame ;
91
+
89
92
@ Override
90
93
public Mat update () {
91
94
if (mjpegHttpReader == null ) return null ;
92
95
93
- byte [] frame = iterator .next ();
96
+ boolean result = InputSourceInitializer .INSTANCE .runWithTimeout (name , () -> {
97
+ frame = iterator .next ();
98
+ return frame != null ;
99
+ });
100
+
101
+ if (!result ) {
102
+ return null ;
103
+ }
94
104
95
105
if (!dataIsValidJPEG (frame )) {
96
106
logger .error ("Received data is not a valid JPEG image" );
@@ -129,15 +139,13 @@ public void close() {
129
139
@ Override
130
140
public void onPause () {
131
141
if (mjpegHttpReader != null ) {
132
- mjpegHttpReader . stop ();
142
+ reset ();
133
143
}
134
144
}
135
145
136
146
@ Override
137
147
public void onResume () {
138
- if (mjpegHttpReader != null ) {
139
- mjpegHttpReader .start ();
140
- }
148
+ InputSourceInitializer .INSTANCE .runWithTimeout (name , eocvSim .inputSourceManager , this ::init );
141
149
}
142
150
143
151
@ Override
@@ -165,10 +173,68 @@ private static boolean dataIsValidJPEG(byte[] data) {
165
173
return false ;
166
174
}
167
175
168
- int totalBytes = data .length ;
176
+ int totalBytes = getJPEGSize (data , data .length );
177
+
178
+ if (totalBytes == -1 ) {
179
+ return false ;
180
+ }
181
+
169
182
return (data [0 ] == (byte ) 0xFF &&
170
183
data [1 ] == (byte ) 0xD8 &&
171
184
data [totalBytes - 2 ] == (byte ) 0xFF &&
172
185
data [totalBytes - 1 ] == (byte ) 0xD9 );
173
186
}
187
+
188
+ private static int getJPEGSize (byte [] data , int maxLength ) {
189
+ if (data == null || maxLength < 4 ) {
190
+ return -1 ; // Invalid or too small to be a JPEG
191
+ }
192
+
193
+ // Check for SOI marker
194
+ if (data [0 ] != (byte ) 0xFF || data [1 ] != (byte ) 0xD8 ) {
195
+ return -1 ; // Not a JPEG
196
+ }
197
+
198
+ int pos = 2 ; // Start after SOI
199
+
200
+ while (pos < maxLength - 2 ) {
201
+ // Look for the next marker (0xFF xx)
202
+ if (data [pos ] == (byte ) 0xFF ) {
203
+ byte marker = data [pos + 1 ];
204
+
205
+ // End of Image (EOI) found
206
+ if (marker == (byte ) 0xD9 ) {
207
+ return pos + 2 ; // JPEG size
208
+ }
209
+
210
+ // Skip padding bytes (some JPEGs use 0xFF 0x00)
211
+ if (marker == (byte ) 0x00 ) {
212
+ pos ++;
213
+ continue ;
214
+ }
215
+
216
+ // Most markers have a 2-byte length field
217
+ if ((marker >= (byte ) 0xC0 && marker <= (byte ) 0xFE ) && marker != (byte ) 0xD9 ) {
218
+ if (pos + 3 >= maxLength ) {
219
+ return -1 ; // Incomplete JPEG
220
+ }
221
+
222
+ // Read segment length (big-endian)
223
+ int segmentLength = ((data [pos + 2 ] & 0xFF ) << 8 ) | (data [pos + 3 ] & 0xFF );
224
+
225
+ if (segmentLength < 2 || pos + segmentLength >= maxLength ) {
226
+ return -1 ; // Corrupt or incomplete JPEG
227
+ }
228
+
229
+ pos += segmentLength ; // Move to next marker
230
+ } else {
231
+ pos ++; // Skip unknown byte
232
+ }
233
+ } else {
234
+ pos ++; // Continue searching
235
+ }
236
+ }
237
+
238
+ return -1 ; // No valid JPEG end found
239
+ }
174
240
}
0 commit comments