Troubleshooting
Common issues and solutions for the Video Mobile SDK.
This guide covers common issues you may encounter when integrating the Video Mobile SDK and how to resolve them.
License errors
License-related issues are the most common cause of SDK failures. These errors typically occur during initialization or when processing images, resulting in black output or exceptions.
Expired certificate
The SDK validates your license on every initialization. An expired certificate will prevent image processing from working correctly.
Symptom: checkCertificate() returns -1 (Android) or checkStatus() returns -1 (iOS). Processed images appear completely black.
Cause: The certificate has passed its expiration date.
Solution:
- Contact EyeQ to obtain a new certificate.
- Update your app with the new credentials.
- If testing, then verify your device date/time is set correctly as incorrect system time can cause valid certificates to appear expired.
Invalid API key or certificate
Mismatched or malformed credentials will prevent the SDK from initializing properly.
Symptom: checkCertificate() returns -2 for Android or checkStatus() returns -2 for iOS.
SDK initialization fails silently.
Cause: The API key and certificate don't match, or one is incorrectly formatted.
Solution:
-
Verify the API key and certificate are from the same license.
-
Check for copy/paste errors such as extra whitespace, missing characters, or truncated strings.
-
On iOS, use raw string literals to avoid escape character issues.
-
On Android, verify credentials in your
setLicence()call:
dynamicProcessor.setLicence(
apiKey = "2128501", // Digits only
cert = "d\\YjDX}mJz...", // Escape backslashes or use raw string
recreate = false
)Checking license status
Always verify your license before processing images. This helps catch configuration issues early.
Android:
val status = dynamicProcessor.checkCertificate(apiKey, cert)
when {
status > 0 -> Log.d("License", "Valid for $status days")
status == -1 -> Log.e("License", "Certificate expired")
status == -2 -> Log.e("License", "Invalid API key or certificate")
else -> Log.e("License", "Unknown error: $status")
}
// Also check days remaining
val daysLeft = dynamicProcessor.getDaysLeft()iOS:
let status = pfcDynamic.checkStatus()
switch status {
case 0:
print("SDK initialized successfully")
case -1:
print("Certificate expired")
case -2:
print("Invalid API key or certificate")
case -3:
print("Failed to initialize AI model")
case -4:
print("Failed to load model file")
case -5:
print("Failed to create context")
default:
print("Unknown error: \(status)")
}Initialization failures
These errors occur when the SDK cannot load or initialize its neural network model. They typically indicate missing dependencies or corrupted framework files.
Failed to initialize AI model
The neural network model requires specific runtime dependencies to execute properly.
Symptom: checkStatus() returns -3 (iOS) or init() throws an exception (Android).
Cause: The TensorFlow Lite runtime could not initialize the neural network model.
Solution for Android:
- Ensure TensorFlow Lite dependencies are included in your
build.gradle:
dependencies {
implementation("org.tensorflow:tensorflow-lite:2.8.0")
implementation("org.tensorflow:tensorflow-lite-gpu:2.8.0")
}- Try CPU fallback if GPU initialization fails:
val gpuSupported = dynamicProcessor.isDelegateSupported()
if (gpuSupported) {
dynamicProcessor.init(useGpu = true)
} else {
dynamicProcessor.init(useGpu = false)
}- On some devices, GPU delegate may be supported but unstable. Use try-catch as a safety net:
try {
dynamicProcessor.init(useGpu = true)
} catch (e: Exception) {
Log.w("SDK", "GPU init failed, falling back to CPU", e)
dynamicProcessor.init(useGpu = false)
}Solution for iOS: The iOS framework bundles all required dependencies. If you see this error, then ensure the XCFramework is properly embedded in your target.
Failed to load model file
The SDK requires a bundled model file to perform image processing.
Symptom: checkStatus() returns -4 (iOS).
Cause: The PFCDynamicModel.pnnc file is missing from the framework bundle.
Solution:
- Re-download the SDK package from EyeQ.
- Verify the XCFramework contains the model file at
DynamicFramework.framework/PFCDynamicModel.pnnc. - In Xcode, clean the build folder (Product → Clean Build Folder) and rebuild.
- Ensure the framework is set to "Embed & Sign" in your target's General settings.
Failed to create context
The SDK requires a GPU context for rendering processed images.
Symptom: checkStatus() returns -5 in iOS.
Cause: OpenGL or Metal context creation failed, typically on simulator or restricted environments.
Solution:
- Test on a physical device instead of the simulator.
- Ensure no other frameworks are holding exclusive GPU resources.
- Check that your app has the necessary entitlements for GPU access.
Build errors
Build-time issues typically relate to project configuration or missing dependencies.
Android: Model file compression
Android's build system may compress SDK model files, corrupting them and preventing the SDK from loading.
Symptom: Model loading fails at runtime with cryptic errors. init() throws an exception.
Solution: Add the noCompress directive to prevent compression of model files:
android {
androidResources {
noCompress("pnn", "pnne")
}
}Android: ProGuard/R8 obfuscation
Code obfuscation can break SDK internals if classes are renamed or removed.
Symptom: SDK works in debug builds but crashes in release builds.
Solution: Add keep rules to your ProGuard configuration:
# Keep SDK classes
-keep class photos.eyeq.dynamic.** { *; }
-keep class photos.eyeq.dynamic.model.** { *; }
-keep class photos.eyeq.dynamic.bench.** { *; }
-keep class photos.eyeq.dynamic.eglx.** { *; }
# Keep TensorFlow Lite
-keep class org.tensorflow.** { *; }
-keepclassmembers class org.tensorflow.** { *; }iOS: Bitcode errors
The SDK framework does not include Bitcode, which can cause archive failures.
Symptom: Build fails with "Bitcode bundle could not be generated" error when archiving.
Solution:
- Select your project in the navigator.
- Go to Build Settings.
- Search for "Enable Bitcode".
- Set to No for your target.
iOS: Framework embedding issues
Incorrect framework configuration causes runtime crashes on app launch.
Symptom: App crashes immediately on launch with "Library not loaded" or "image not found" errors.
Solution:
- Select your target in Xcode.
- Go to General → Frameworks, Libraries, and Embedded Content.
- Ensure
DynamicFramework.xcframeworkis set to Embed & Sign. - If using CocoaPods or SPM, then ensure the framework is properly linked.
Performance issues
If you're experiencing slow frame rates, laggy preview, or excessive battery drain, then these optimizations can help.
Slow processing speed
Processing speed depends on image resolution, device hardware, and whether GPU acceleration is active.
Diagnosis: Use benchmarking to identify which stage is the bottleneck.
Android:
dynamicProcessor.setBenchListener(object : EyeQBenchListener {
override fun onDynamic(bench: BenchDynamic) {
Log.d("Perf", "Scale: ${bench.scaleTime}ms")
Log.d("Perf", "Read bitmap: ${bench.readFromBitmap}ms")
Log.d("Perf", "Normalize: ${bench.normalizeTime}ms")
Log.d("Perf", "Inference: ${bench.inferenceTime}ms")
Log.d("Perf", "Adjust: ${bench.adjustTime}ms")
}
override fun onEgl(bench: BenchEgl) {
Log.d("Perf", "Texture: ${bench.textureTime}ms")
Log.d("Perf", "Render: ${bench.renderTime}ms")
}
override fun onDeflicker(consumeTime: Long) {
Log.d("Perf", "Deflicker: ${consumeTime}ms")
}
})Optimizations:
- Verify GPU is active: Check that GPU delegate is supported and being used:
val gpuSupported = dynamicProcessor.isDelegateSupported()
Log.d("SDK", "GPU supported: $gpuSupported")- Use frame skipping: For video processing, skip frames to reduce load:
// Skip 1 frame between inferences (process every other frame)
dynamicProcessor.setDeflickerParams(1, 0.08f, 0.9f)- Use preview methods: For display purposes, use
processImagePreview()orprocessCameraFrame()instead ofprocessImage().
iOS optimizations:
- Enable frame skipping: Reduce processing load on lower-end devices:
// Skip 1 frame between inferences
pfcDynamic.setParams(deflickerCurve: 0.08, deflickerImage: 0.9, skip: 1)- Process on background queue: Never block the main thread:
videoQueue.async {
let processed = try? self.pfcDynamic.processImage(cgImage, strength: 0.8)
DispatchQueue.main.async {
self.imageView.image = UIImage(cgImage: processed)
}
}Video flickering
Flickering in video output occurs when correction parameters vary frame-to-frame without temporal smoothing.
Cause: Deflickering not configured, or resetDeflicker() called too frequently.
Solution:
- Enable deflickering: Before processing video frames:
// iOS
pfcDynamic.setParams(deflickerCurve: 0.08, deflickerImage: 0.9, skip: 0)// Android
dynamicProcessor.setDeflickerParams(0, 0.08f, 0.9f)- Only reset when necessary: Call
resetDeflicker()only in these situations:
| Scenario | Action |
|---|---|
| Switching cameras | Call resetDeflicker() |
| Starting new video | Call resetDeflicker() |
| Seeking in video | Call resetDeflicker() |
| Each frame | ❌ Never call per-frame |
- Don't call during active processing: Calling
setDeflickerParams()while processing frames can cause visual discontinuities.
Memory issues
Processing high-resolution images can consume significant memory, especially on older devices.
Android:
// Recycle bitmaps when done
processedBitmap.recycle()
// For camera processing, close ImageProxy promptly
imageProxy.close()iOS:
// Use autoreleasepool for batch processing
for image in images {
autoreleasepool {
let processed = try? pfcDynamic.processImage(image, strength: 0.8)
// Use processed image
}
}Platform-specific issues
Some issues only occur on specific platforms due to framework conflicts or platform limitations.
iOS: Simulator limitations
The iOS Simulator has limited GPU capabilities and no camera access.
What works: Basic image processing with processImage().
What doesn't work: Camera capture, real-time video processing, accurate performance testing.
Solution: Always test video and camera features on a physical device.
iOS: GPUImage conflicts
The SDK uses GPUImage internally, which can conflict with external GPUImage dependencies.
Symptom: Crashes or undefined behavior when using GPUImage framework alongside the SDK.
Solution:
- Remove external GPUImage dependency if possible.
- If you must use GPUImage, then isolate SDK usage in a separate module or process.
- Contact EyeQ support for guidance on specific conflict scenarios.
Android: Camera2/CameraX compatibility
Some camera implementations produce image formats that require conversion before SDK processing.
Symptom: Processed images appear corrupted or have wrong colors.
Solution: Use the SDK's YuvToRgbConverter for camera frames:
val converter = YuvToRgbConverter(context)
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
// Convert camera frame
converter.yuvToRgb(image, bitmap)
// Process converted bitmap
val outputs = dynamicProcessor.processCameraFrame(bitmap, 0.8f)Getting help
If you encounter issues not covered in this guide, here's how to get additional support.
Before contacting support:
- Review the sample projects for working implementation examples.
- Check the API reference for Android or iOS.
- Verify your SDK version matches the documentation.
When contacting EyeQ support, include:
- SDK version number
- Platform and OS version, for example, Android 16, iOS 18
- Device model
- Complete error message or stack trace
- Minimal code sample that reproduces the issue
- Output of
checkCertificate()orcheckStatus()
VIDEO-SDK Version 1.0.0.23 built from aa5eef97017e23db1d3051b079500606825ef474 on 5-6-2023.
Copyright © 2026 EyeQ Imaging Inc. All rights reserved.